refactor(proposal): use id newtypes across the governance path
This commit is contained in:
@@ -8,7 +8,8 @@ use crate::{
|
|||||||
self,
|
self,
|
||||||
models::{
|
models::{
|
||||||
NewProposal, NewProposalVote, NewRecoveryProposalVote, NewRecoveryWakeupRequest,
|
NewProposal, NewProposalVote, NewRecoveryProposalVote, NewRecoveryWakeupRequest,
|
||||||
Proposal, ProposalStatus, SqliteTimestamp,
|
OperatorIdentityId, Proposal, ProposalId, ProposalStatus, RecoveryOperatorIdentityId,
|
||||||
|
SqliteTimestamp,
|
||||||
},
|
},
|
||||||
proposal::{ProposalKind, ProposalKindTag, one_off_transaction, persistent_grant},
|
proposal::{ProposalKind, ProposalKindTag, one_off_transaction, persistent_grant},
|
||||||
schema,
|
schema,
|
||||||
@@ -65,9 +66,9 @@ pub enum Error {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ProposalSummary {
|
pub struct ProposalSummary {
|
||||||
pub id: i32,
|
pub id: ProposalId,
|
||||||
pub kind: ProposalKindTag,
|
pub kind: ProposalKindTag,
|
||||||
pub initiator_id: i32,
|
pub initiator_id: OperatorIdentityId,
|
||||||
pub expires_at: SqliteTimestamp,
|
pub expires_at: SqliteTimestamp,
|
||||||
pub approve_count: i64,
|
pub approve_count: i64,
|
||||||
pub reject_count: i64,
|
pub reject_count: i64,
|
||||||
@@ -103,9 +104,9 @@ impl ProposalManager {
|
|||||||
pub async fn create_proposal(
|
pub async fn create_proposal(
|
||||||
&mut self,
|
&mut self,
|
||||||
kind: ProposalKind,
|
kind: ProposalKind,
|
||||||
initiator_id: i32,
|
initiator_id: OperatorIdentityId,
|
||||||
ttl_secs: Option<u32>,
|
ttl_secs: Option<u32>,
|
||||||
) -> Result<i32, Error> {
|
) -> Result<ProposalId, Error> {
|
||||||
let ttl = ttl_secs.unwrap_or(DEFAULT_TTL_SECS);
|
let ttl = ttl_secs.unwrap_or(DEFAULT_TTL_SECS);
|
||||||
if ttl > MAX_TTL_SECS {
|
if ttl > MAX_TTL_SECS {
|
||||||
return Err(Error::TtlTooLong);
|
return Err(Error::TtlTooLong);
|
||||||
@@ -113,12 +114,12 @@ impl ProposalManager {
|
|||||||
let expires_at =
|
let expires_at =
|
||||||
SqliteTimestamp::from(Utc::now() + chrono::Duration::seconds(i64::from(ttl)));
|
SqliteTimestamp::from(Utc::now() + chrono::Duration::seconds(i64::from(ttl)));
|
||||||
|
|
||||||
let id: i32 = self
|
let id: ProposalId = self
|
||||||
.db
|
.db
|
||||||
.get()
|
.get()
|
||||||
.await?
|
.await?
|
||||||
.transaction(async |conn| {
|
.transaction(async |conn| {
|
||||||
let id: i32 = diesel::insert_into(schema::proposal::table)
|
let id: ProposalId = diesel::insert_into(schema::proposal::table)
|
||||||
.values(&NewProposal {
|
.values(&NewProposal {
|
||||||
kind: kind.discriminant(),
|
kind: kind.discriminant(),
|
||||||
initiator_id,
|
initiator_id,
|
||||||
@@ -136,7 +137,7 @@ impl ProposalManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[message]
|
#[message]
|
||||||
pub async fn query_pending(&mut self, operator_id: i32) -> Vec<ProposalSummary> {
|
pub async fn query_pending(&mut self, operator_id: OperatorIdentityId) -> Vec<ProposalSummary> {
|
||||||
#[expect(
|
#[expect(
|
||||||
clippy::cast_possible_truncation,
|
clippy::cast_possible_truncation,
|
||||||
clippy::as_conversions,
|
clippy::as_conversions,
|
||||||
@@ -149,7 +150,7 @@ impl ProposalManager {
|
|||||||
return vec![];
|
return vec![];
|
||||||
};
|
};
|
||||||
|
|
||||||
let voted_ids: Vec<i32> = schema::proposal_vote::table
|
let voted_ids: Vec<ProposalId> = schema::proposal_vote::table
|
||||||
.filter(schema::proposal_vote::operator_id.eq(operator_id))
|
.filter(schema::proposal_vote::operator_id.eq(operator_id))
|
||||||
.select(schema::proposal_vote::proposal_id)
|
.select(schema::proposal_vote::proposal_id)
|
||||||
.load(&mut conn)
|
.load(&mut conn)
|
||||||
@@ -195,8 +196,8 @@ impl ProposalManager {
|
|||||||
#[message]
|
#[message]
|
||||||
pub async fn cast_vote(
|
pub async fn cast_vote(
|
||||||
&mut self,
|
&mut self,
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
operator_id: i32,
|
operator_id: OperatorIdentityId,
|
||||||
approve: bool,
|
approve: bool,
|
||||||
signature: Vec<u8>,
|
signature: Vec<u8>,
|
||||||
) -> Result<VoteOutcome, Error> {
|
) -> Result<VoteOutcome, Error> {
|
||||||
@@ -249,7 +250,7 @@ impl ProposalManager {
|
|||||||
|
|
||||||
// Canonical vote message: proposal_id (i64 big-endian) || approve (u8)
|
// Canonical vote message: proposal_id (i64 big-endian) || approve (u8)
|
||||||
let mut vote_msg = Vec::with_capacity(9);
|
let mut vote_msg = Vec::with_capacity(9);
|
||||||
vote_msg.extend_from_slice(&i64::from(proposal_id).to_be_bytes());
|
vote_msg.extend_from_slice(&i64::from(proposal_id.to_raw()).to_be_bytes());
|
||||||
vote_msg.push(u8::from(approve));
|
vote_msg.push(u8::from(approve));
|
||||||
|
|
||||||
let auth_sig = authn::Signature::try_from(signature.as_slice())
|
let auth_sig = authn::Signature::try_from(signature.as_slice())
|
||||||
@@ -358,7 +359,10 @@ impl ProposalManager {
|
|||||||
/// §3.6: Any ordinary operator may request recovery wake-up.
|
/// §3.6: Any ordinary operator may request recovery wake-up.
|
||||||
/// Fails if a wake-up is already pending or active.
|
/// Fails if a wake-up is already pending or active.
|
||||||
#[message]
|
#[message]
|
||||||
pub async fn request_recovery_wakeup(&mut self, operator_id: i32) -> Result<(), Error> {
|
pub async fn request_recovery_wakeup(
|
||||||
|
&mut self,
|
||||||
|
operator_id: OperatorIdentityId,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let mut conn = self.db.get().await?;
|
let mut conn = self.db.get().await?;
|
||||||
if Self::has_uncancelled_wakeup(&mut conn).await? {
|
if Self::has_uncancelled_wakeup(&mut conn).await? {
|
||||||
return Err(Error::WakeupAlreadyPending);
|
return Err(Error::WakeupAlreadyPending);
|
||||||
@@ -375,7 +379,10 @@ impl ProposalManager {
|
|||||||
/// §3.6: Any ordinary operator may cancel a pending wake-up request.
|
/// §3.6: Any ordinary operator may cancel a pending wake-up request.
|
||||||
/// Fails if there is no uncancelled request.
|
/// Fails if there is no uncancelled request.
|
||||||
#[message]
|
#[message]
|
||||||
pub async fn cancel_recovery_wakeup(&mut self, operator_id: i32) -> Result<(), Error> {
|
pub async fn cancel_recovery_wakeup(
|
||||||
|
&mut self,
|
||||||
|
operator_id: OperatorIdentityId,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let mut conn = self.db.get().await?;
|
let mut conn = self.db.get().await?;
|
||||||
let rows_updated = diesel::update(schema::recovery_wakeup_request::table)
|
let rows_updated = diesel::update(schema::recovery_wakeup_request::table)
|
||||||
.filter(schema::recovery_wakeup_request::cancelled_at.is_null())
|
.filter(schema::recovery_wakeup_request::cancelled_at.is_null())
|
||||||
@@ -396,8 +403,8 @@ impl ProposalManager {
|
|||||||
#[message]
|
#[message]
|
||||||
pub async fn cast_recovery_vote(
|
pub async fn cast_recovery_vote(
|
||||||
&mut self,
|
&mut self,
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
recovery_operator_id: i32,
|
recovery_operator_id: RecoveryOperatorIdentityId,
|
||||||
approve: bool,
|
approve: bool,
|
||||||
signature: Vec<u8>,
|
signature: Vec<u8>,
|
||||||
) -> Result<VoteOutcome, Error> {
|
) -> Result<VoteOutcome, Error> {
|
||||||
@@ -454,7 +461,7 @@ impl ProposalManager {
|
|||||||
.map_err(|()| Error::InvalidSignature)?;
|
.map_err(|()| Error::InvalidSignature)?;
|
||||||
|
|
||||||
let mut vote_msg = Vec::with_capacity(9);
|
let mut vote_msg = Vec::with_capacity(9);
|
||||||
vote_msg.extend_from_slice(&i64::from(proposal_id).to_be_bytes());
|
vote_msg.extend_from_slice(&i64::from(proposal_id.to_raw()).to_be_bytes());
|
||||||
vote_msg.push(u8::from(approve));
|
vote_msg.push(u8::from(approve));
|
||||||
|
|
||||||
let auth_sig = authn::Signature::try_from(signature.as_slice())
|
let auth_sig = authn::Signature::try_from(signature.as_slice())
|
||||||
@@ -617,7 +624,7 @@ impl ProposalManager {
|
|||||||
/// removes their old Shamir share, then begins a coordinated re-key (§3.3).
|
/// removes their old Shamir share, then begins a coordinated re-key (§3.3).
|
||||||
async fn execute_replace_operator(
|
async fn execute_replace_operator(
|
||||||
&self,
|
&self,
|
||||||
old_operator_id: i32,
|
old_operator_id: OperatorIdentityId,
|
||||||
new_pubkey: Vec<u8>,
|
new_pubkey: Vec<u8>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut conn = self.db.get().await.map_err(Error::DatabaseConnection)?;
|
let mut conn = self.db.get().await.map_err(Error::DatabaseConnection)?;
|
||||||
@@ -657,7 +664,7 @@ impl ProposalManager {
|
|||||||
|
|
||||||
async fn execute_approve_one_off_transaction(
|
async fn execute_approve_one_off_transaction(
|
||||||
&self,
|
&self,
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
tx: one_off_transaction::Settings,
|
tx: one_off_transaction::Settings,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
use crate::actors::evm::ClientSignTransaction;
|
use crate::actors::evm::ClientSignTransaction;
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ pub mod types {
|
|||||||
declare_id!(TlsHistoryId);
|
declare_id!(TlsHistoryId);
|
||||||
declare_id!(EvmWalletId);
|
declare_id!(EvmWalletId);
|
||||||
declare_id!(ClientId);
|
declare_id!(ClientId);
|
||||||
|
declare_id!(ProposalId);
|
||||||
|
declare_id!(RecoveryOperatorIdentityId);
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, AsExpression, FromSqlRow)]
|
#[derive(Debug, Clone, PartialEq, Eq, AsExpression, FromSqlRow)]
|
||||||
#[diesel(sql_type = Text)]
|
#[diesel(sql_type = Text)]
|
||||||
@@ -478,9 +480,9 @@ pub struct IntegrityEnvelope {
|
|||||||
#[derive(Debug, Queryable, Selectable, Identifiable)]
|
#[derive(Debug, Queryable, Selectable, Identifiable)]
|
||||||
#[diesel(table_name = schema::proposal, check_for_backend(Sqlite))]
|
#[diesel(table_name = schema::proposal, check_for_backend(Sqlite))]
|
||||||
pub struct Proposal {
|
pub struct Proposal {
|
||||||
pub id: i32,
|
pub id: ProposalId,
|
||||||
pub kind: ProposalKindTag,
|
pub kind: ProposalKindTag,
|
||||||
pub initiator_id: i32,
|
pub initiator_id: OperatorIdentityId,
|
||||||
pub created_at: SqliteTimestamp,
|
pub created_at: SqliteTimestamp,
|
||||||
pub expires_at: SqliteTimestamp,
|
pub expires_at: SqliteTimestamp,
|
||||||
pub status: ProposalStatus,
|
pub status: ProposalStatus,
|
||||||
@@ -490,7 +492,7 @@ pub struct Proposal {
|
|||||||
#[diesel(table_name = schema::proposal, check_for_backend(Sqlite))]
|
#[diesel(table_name = schema::proposal, check_for_backend(Sqlite))]
|
||||||
pub struct NewProposal {
|
pub struct NewProposal {
|
||||||
pub kind: ProposalKindTag,
|
pub kind: ProposalKindTag,
|
||||||
pub initiator_id: i32,
|
pub initiator_id: OperatorIdentityId,
|
||||||
// status defaults to 'pending' at the DB layer
|
// status defaults to 'pending' at the DB layer
|
||||||
pub expires_at: SqliteTimestamp,
|
pub expires_at: SqliteTimestamp,
|
||||||
}
|
}
|
||||||
@@ -499,8 +501,8 @@ pub struct NewProposal {
|
|||||||
#[diesel(table_name = schema::proposal_vote, check_for_backend(Sqlite))]
|
#[diesel(table_name = schema::proposal_vote, check_for_backend(Sqlite))]
|
||||||
pub struct ProposalVote {
|
pub struct ProposalVote {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub proposal_id: i32,
|
pub proposal_id: ProposalId,
|
||||||
pub operator_id: i32,
|
pub operator_id: OperatorIdentityId,
|
||||||
pub approve: bool,
|
pub approve: bool,
|
||||||
pub signature: Vec<u8>,
|
pub signature: Vec<u8>,
|
||||||
pub voted_at: SqliteTimestamp,
|
pub voted_at: SqliteTimestamp,
|
||||||
@@ -509,8 +511,8 @@ pub struct ProposalVote {
|
|||||||
#[derive(Debug, Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = schema::proposal_vote, check_for_backend(Sqlite))]
|
#[diesel(table_name = schema::proposal_vote, check_for_backend(Sqlite))]
|
||||||
pub struct NewProposalVote {
|
pub struct NewProposalVote {
|
||||||
pub proposal_id: i32,
|
pub proposal_id: ProposalId,
|
||||||
pub operator_id: i32,
|
pub operator_id: OperatorIdentityId,
|
||||||
pub approve: bool,
|
pub approve: bool,
|
||||||
pub signature: Vec<u8>,
|
pub signature: Vec<u8>,
|
||||||
}
|
}
|
||||||
@@ -518,8 +520,8 @@ pub struct NewProposalVote {
|
|||||||
#[derive(Debug, Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = schema::recovery_proposal_vote, check_for_backend(Sqlite))]
|
#[diesel(table_name = schema::recovery_proposal_vote, check_for_backend(Sqlite))]
|
||||||
pub struct NewRecoveryProposalVote {
|
pub struct NewRecoveryProposalVote {
|
||||||
pub proposal_id: i32,
|
pub proposal_id: ProposalId,
|
||||||
pub recovery_operator_id: i32,
|
pub recovery_operator_id: RecoveryOperatorIdentityId,
|
||||||
pub approve: bool,
|
pub approve: bool,
|
||||||
pub signature: Vec<u8>,
|
pub signature: Vec<u8>,
|
||||||
}
|
}
|
||||||
@@ -527,5 +529,5 @@ pub struct NewRecoveryProposalVote {
|
|||||||
#[derive(Debug, Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = schema::recovery_wakeup_request, check_for_backend(Sqlite))]
|
#[diesel(table_name = schema::recovery_wakeup_request, check_for_backend(Sqlite))]
|
||||||
pub struct NewRecoveryWakeupRequest {
|
pub struct NewRecoveryWakeupRequest {
|
||||||
pub requested_by: i32,
|
pub requested_by: OperatorIdentityId,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
//! Approving an SDK client so it may authenticate against the vault.
|
//! Approving an SDK client so it may authenticate against the vault.
|
||||||
|
|
||||||
use super::{Proposal, ProposalKindTag};
|
use super::{Proposal, ProposalKindTag};
|
||||||
use crate::db::{DatabaseConnection, schema::proposal_approve_sdk_client as table};
|
use crate::db::{
|
||||||
|
DatabaseConnection, models::ProposalId, schema::proposal_approve_sdk_client as table,
|
||||||
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
ExpressionMethods as _, Insertable, QueryDsl as _, QueryResult, Queryable, Selectable,
|
ExpressionMethods as _, Insertable, QueryDsl as _, QueryResult, Queryable, Selectable,
|
||||||
SelectableHelper as _, sqlite::Sqlite,
|
SelectableHelper as _, sqlite::Sqlite,
|
||||||
@@ -22,7 +24,7 @@ impl Proposal for ApproveSdkClient {
|
|||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
|
|
||||||
async fn insert(
|
async fn insert(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
settings: &Self::Settings,
|
settings: &Self::Settings,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
@@ -33,7 +35,10 @@ impl Proposal for ApproveSdkClient {
|
|||||||
.map(drop)
|
.map(drop)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load(proposal_id: i32, conn: &mut DatabaseConnection) -> QueryResult<Self::Settings> {
|
async fn load(
|
||||||
|
proposal_id: ProposalId,
|
||||||
|
conn: &mut DatabaseConnection,
|
||||||
|
) -> QueryResult<Self::Settings> {
|
||||||
table::table
|
table::table
|
||||||
.find(proposal_id)
|
.find(proposal_id)
|
||||||
.select(Settings::as_select())
|
.select(Settings::as_select())
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
//! Granting an SDK client visibility of a wallet.
|
//! Granting an SDK client visibility of a wallet.
|
||||||
|
|
||||||
use super::{Proposal, ProposalKindTag};
|
use super::{Proposal, ProposalKindTag};
|
||||||
use crate::db::{DatabaseConnection, schema::proposal_grant_wallet_access as table};
|
use crate::db::{
|
||||||
|
DatabaseConnection, models::ProposalId, schema::proposal_grant_wallet_access as table,
|
||||||
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
ExpressionMethods as _, Insertable, QueryDsl as _, QueryResult, Queryable, Selectable,
|
ExpressionMethods as _, Insertable, QueryDsl as _, QueryResult, Queryable, Selectable,
|
||||||
SelectableHelper as _, sqlite::Sqlite,
|
SelectableHelper as _, sqlite::Sqlite,
|
||||||
@@ -23,7 +25,7 @@ impl Proposal for GrantWalletAccess {
|
|||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
|
|
||||||
async fn insert(
|
async fn insert(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
settings: &Self::Settings,
|
settings: &Self::Settings,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
@@ -34,7 +36,10 @@ impl Proposal for GrantWalletAccess {
|
|||||||
.map(drop)
|
.map(drop)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load(proposal_id: i32, conn: &mut DatabaseConnection) -> QueryResult<Self::Settings> {
|
async fn load(
|
||||||
|
proposal_id: ProposalId,
|
||||||
|
conn: &mut DatabaseConnection,
|
||||||
|
) -> QueryResult<Self::Settings> {
|
||||||
table::table
|
table::table
|
||||||
.find(proposal_id)
|
.find(proposal_id)
|
||||||
.select(Settings::as_select())
|
.select(Settings::as_select())
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//! new kind is a new module plus one arm in each dispatcher -- nothing else in the
|
//! new kind is a new module plus one arm in each dispatcher -- nothing else in the
|
||||||
//! codebase has to learn about it.
|
//! codebase has to learn about it.
|
||||||
|
|
||||||
use crate::db::DatabaseConnection;
|
use crate::db::{DatabaseConnection, models::ProposalId};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
QueryResult,
|
QueryResult,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
@@ -42,7 +42,7 @@ pub trait Proposal: Sized {
|
|||||||
|
|
||||||
/// Writes the child row carrying `settings`.
|
/// Writes the child row carrying `settings`.
|
||||||
fn insert(
|
fn insert(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
settings: &Self::Settings,
|
settings: &Self::Settings,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> impl Future<Output = QueryResult<()>> + Send;
|
) -> impl Future<Output = QueryResult<()>> + Send;
|
||||||
@@ -50,7 +50,7 @@ pub trait Proposal: Sized {
|
|||||||
/// Reads the child row back. A missing row surfaces as [`diesel::result::Error::NotFound`],
|
/// Reads the child row back. A missing row surfaces as [`diesel::result::Error::NotFound`],
|
||||||
/// which is what a proposal without its parameters is.
|
/// which is what a proposal without its parameters is.
|
||||||
fn load(
|
fn load(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> impl Future<Output = QueryResult<Self::Settings>> + Send;
|
) -> impl Future<Output = QueryResult<Self::Settings>> + Send;
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ const _: () = {
|
|||||||
/// to the implementation that owns the table.
|
/// to the implementation that owns the table.
|
||||||
pub async fn insert_kind(
|
pub async fn insert_kind(
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
kind: &ProposalKind,
|
kind: &ProposalKind,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
match kind {
|
match kind {
|
||||||
@@ -146,7 +146,7 @@ pub async fn insert_kind(
|
|||||||
/// Reads the parameters back for a `proposal.kind` that is only known at runtime.
|
/// Reads the parameters back for a `proposal.kind` that is only known at runtime.
|
||||||
pub async fn load_kind(
|
pub async fn load_kind(
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
tag: ProposalKindTag,
|
tag: ProposalKindTag,
|
||||||
) -> QueryResult<ProposalKind> {
|
) -> QueryResult<ProposalKind> {
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
use super::{Proposal, ProposalKindTag, as_i64, as_u64, fixed};
|
use super::{Proposal, ProposalKindTag, as_i64, as_u64, fixed};
|
||||||
use crate::db::{
|
use crate::db::{
|
||||||
DatabaseConnection,
|
DatabaseConnection,
|
||||||
|
models::ProposalId,
|
||||||
schema::{proposal_one_off_transaction, proposal_one_off_transaction_result},
|
schema::{proposal_one_off_transaction, proposal_one_off_transaction_result},
|
||||||
};
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
@@ -28,7 +29,7 @@ pub struct Settings {
|
|||||||
#[derive(Debug, Queryable, Selectable, Insertable)]
|
#[derive(Debug, Queryable, Selectable, Insertable)]
|
||||||
#[diesel(table_name = proposal_one_off_transaction, check_for_backend(Sqlite))]
|
#[diesel(table_name = proposal_one_off_transaction, check_for_backend(Sqlite))]
|
||||||
struct Row {
|
struct Row {
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
client_id: i32,
|
client_id: i32,
|
||||||
wallet_address: Vec<u8>,
|
wallet_address: Vec<u8>,
|
||||||
chain_id: i64,
|
chain_id: i64,
|
||||||
@@ -42,7 +43,7 @@ struct Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Row {
|
impl Row {
|
||||||
fn new(proposal_id: i32, settings: &Settings) -> QueryResult<Self> {
|
fn new(proposal_id: ProposalId, settings: &Settings) -> QueryResult<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
proposal_id,
|
proposal_id,
|
||||||
client_id: settings.client_id,
|
client_id: settings.client_id,
|
||||||
@@ -82,7 +83,7 @@ impl Proposal for OneOffTransaction {
|
|||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
|
|
||||||
async fn insert(
|
async fn insert(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
settings: &Self::Settings,
|
settings: &Self::Settings,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
@@ -93,7 +94,10 @@ impl Proposal for OneOffTransaction {
|
|||||||
.map(drop)
|
.map(drop)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load(proposal_id: i32, conn: &mut DatabaseConnection) -> QueryResult<Self::Settings> {
|
async fn load(
|
||||||
|
proposal_id: ProposalId,
|
||||||
|
conn: &mut DatabaseConnection,
|
||||||
|
) -> QueryResult<Self::Settings> {
|
||||||
let row: Row = proposal_one_off_transaction::table
|
let row: Row = proposal_one_off_transaction::table
|
||||||
.find(proposal_id)
|
.find(proposal_id)
|
||||||
.select(Row::as_select())
|
.select(Row::as_select())
|
||||||
@@ -108,7 +112,7 @@ impl Proposal for OneOffTransaction {
|
|||||||
#[derive(Debug, Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = proposal_one_off_transaction_result, check_for_backend(Sqlite))]
|
#[diesel(table_name = proposal_one_off_transaction_result, check_for_backend(Sqlite))]
|
||||||
struct SignatureRow {
|
struct SignatureRow {
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
r: Vec<u8>,
|
r: Vec<u8>,
|
||||||
s: Vec<u8>,
|
s: Vec<u8>,
|
||||||
y_parity: i32,
|
y_parity: i32,
|
||||||
@@ -117,7 +121,7 @@ struct SignatureRow {
|
|||||||
/// Records the signature produced for an approved transaction, by component, so what
|
/// Records the signature produced for an approved transaction, by component, so what
|
||||||
/// came back is as readable as what was signed.
|
/// came back is as readable as what was signed.
|
||||||
pub async fn store_signature(
|
pub async fn store_signature(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
signature: &alloy::signers::Signature,
|
signature: &alloy::signers::Signature,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
use super::{Proposal, ProposalKindTag, as_i64, as_u64, fixed};
|
use super::{Proposal, ProposalKindTag, as_i64, as_u64, fixed};
|
||||||
use crate::db::{
|
use crate::db::{
|
||||||
DatabaseConnection,
|
DatabaseConnection,
|
||||||
|
models::ProposalId,
|
||||||
schema::{
|
schema::{
|
||||||
proposal_persistent_grant, proposal_persistent_grant_ether,
|
proposal_persistent_grant, proposal_persistent_grant_ether,
|
||||||
proposal_persistent_grant_ether_target, proposal_persistent_grant_token,
|
proposal_persistent_grant_ether_target, proposal_persistent_grant_token,
|
||||||
@@ -55,7 +56,7 @@ pub enum Specific {
|
|||||||
#[derive(Debug, Queryable, Selectable, Insertable)]
|
#[derive(Debug, Queryable, Selectable, Insertable)]
|
||||||
#[diesel(table_name = proposal_persistent_grant, check_for_backend(Sqlite))]
|
#[diesel(table_name = proposal_persistent_grant, check_for_backend(Sqlite))]
|
||||||
struct BaseRow {
|
struct BaseRow {
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
wallet_access_id: i32,
|
wallet_access_id: i32,
|
||||||
chain_id: i64,
|
chain_id: i64,
|
||||||
valid_from: Option<i64>,
|
valid_from: Option<i64>,
|
||||||
@@ -69,7 +70,7 @@ struct BaseRow {
|
|||||||
#[derive(Debug, Queryable, Selectable, Insertable)]
|
#[derive(Debug, Queryable, Selectable, Insertable)]
|
||||||
#[diesel(table_name = proposal_persistent_grant_ether, check_for_backend(Sqlite))]
|
#[diesel(table_name = proposal_persistent_grant_ether, check_for_backend(Sqlite))]
|
||||||
struct EtherRow {
|
struct EtherRow {
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
window_secs: i64,
|
window_secs: i64,
|
||||||
max_volume: Vec<u8>,
|
max_volume: Vec<u8>,
|
||||||
}
|
}
|
||||||
@@ -77,14 +78,14 @@ struct EtherRow {
|
|||||||
#[derive(Debug, Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = proposal_persistent_grant_ether_target, check_for_backend(Sqlite))]
|
#[diesel(table_name = proposal_persistent_grant_ether_target, check_for_backend(Sqlite))]
|
||||||
struct NewEtherTarget {
|
struct NewEtherTarget {
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
address: Vec<u8>,
|
address: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Queryable, Selectable, Insertable)]
|
#[derive(Debug, Queryable, Selectable, Insertable)]
|
||||||
#[diesel(table_name = proposal_persistent_grant_token, check_for_backend(Sqlite))]
|
#[diesel(table_name = proposal_persistent_grant_token, check_for_backend(Sqlite))]
|
||||||
struct TokenRow {
|
struct TokenRow {
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
token_contract: Vec<u8>,
|
token_contract: Vec<u8>,
|
||||||
receiver: Option<Vec<u8>>,
|
receiver: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
@@ -92,13 +93,13 @@ struct TokenRow {
|
|||||||
#[derive(Debug, Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = proposal_persistent_grant_token_limit, check_for_backend(Sqlite))]
|
#[diesel(table_name = proposal_persistent_grant_token_limit, check_for_backend(Sqlite))]
|
||||||
struct NewTokenLimit {
|
struct NewTokenLimit {
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
window_secs: i64,
|
window_secs: i64,
|
||||||
max_volume: Vec<u8>,
|
max_volume: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseRow {
|
impl BaseRow {
|
||||||
fn new(proposal_id: i32, settings: &Settings) -> QueryResult<Self> {
|
fn new(proposal_id: ProposalId, settings: &Settings) -> QueryResult<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
proposal_id,
|
proposal_id,
|
||||||
wallet_access_id: settings.wallet_access_id,
|
wallet_access_id: settings.wallet_access_id,
|
||||||
@@ -141,7 +142,7 @@ impl Proposal for PersistentGrant {
|
|||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
|
|
||||||
async fn insert(
|
async fn insert(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
settings: &Self::Settings,
|
settings: &Self::Settings,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
@@ -201,7 +202,10 @@ impl Proposal for PersistentGrant {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load(proposal_id: i32, conn: &mut DatabaseConnection) -> QueryResult<Self::Settings> {
|
async fn load(
|
||||||
|
proposal_id: ProposalId,
|
||||||
|
conn: &mut DatabaseConnection,
|
||||||
|
) -> QueryResult<Self::Settings> {
|
||||||
let base: BaseRow = proposal_persistent_grant::table
|
let base: BaseRow = proposal_persistent_grant::table
|
||||||
.find(proposal_id)
|
.find(proposal_id)
|
||||||
.select(BaseRow::as_select())
|
.select(BaseRow::as_select())
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
//! Replacing an operator's key, which also triggers a Shamir re-key (§3.3).
|
//! Replacing an operator's key, which also triggers a Shamir re-key (§3.3).
|
||||||
|
|
||||||
use super::{Proposal, ProposalKindTag};
|
use super::{Proposal, ProposalKindTag};
|
||||||
use crate::db::{DatabaseConnection, schema::proposal_replace_operator as table};
|
use crate::db::{
|
||||||
|
DatabaseConnection,
|
||||||
|
models::{OperatorIdentityId, ProposalId},
|
||||||
|
schema::proposal_replace_operator as table,
|
||||||
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
ExpressionMethods as _, Insertable, QueryDsl as _, QueryResult, Queryable, Selectable,
|
ExpressionMethods as _, Insertable, QueryDsl as _, QueryResult, Queryable, Selectable,
|
||||||
SelectableHelper as _, sqlite::Sqlite,
|
SelectableHelper as _, sqlite::Sqlite,
|
||||||
@@ -11,7 +15,7 @@ use diesel_async::RunQueryDsl as _;
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq, Queryable, Selectable, Insertable)]
|
#[derive(Debug, Clone, PartialEq, Eq, Queryable, Selectable, Insertable)]
|
||||||
#[diesel(table_name = table, check_for_backend(Sqlite))]
|
#[diesel(table_name = table, check_for_backend(Sqlite))]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub old_operator_id: i32,
|
pub old_operator_id: OperatorIdentityId,
|
||||||
pub new_pubkey: Vec<u8>,
|
pub new_pubkey: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,7 +27,7 @@ impl Proposal for ReplaceOperator {
|
|||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
|
|
||||||
async fn insert(
|
async fn insert(
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
settings: &Self::Settings,
|
settings: &Self::Settings,
|
||||||
conn: &mut DatabaseConnection,
|
conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
@@ -34,7 +38,10 @@ impl Proposal for ReplaceOperator {
|
|||||||
.map(drop)
|
.map(drop)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load(proposal_id: i32, conn: &mut DatabaseConnection) -> QueryResult<Self::Settings> {
|
async fn load(
|
||||||
|
proposal_id: ProposalId,
|
||||||
|
conn: &mut DatabaseConnection,
|
||||||
|
) -> QueryResult<Self::Settings> {
|
||||||
table::table
|
table::table
|
||||||
.find(proposal_id)
|
.find(proposal_id)
|
||||||
.select(Settings::as_select())
|
.select(Settings::as_select())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! A Shamir re-key over the current operator set (§3.3).
|
//! A Shamir re-key over the current operator set (§3.3).
|
||||||
|
|
||||||
use super::{Proposal, ProposalKindTag};
|
use super::{Proposal, ProposalKindTag};
|
||||||
use crate::db::DatabaseConnection;
|
use crate::db::{DatabaseConnection, models::ProposalId};
|
||||||
use diesel::QueryResult;
|
use diesel::QueryResult;
|
||||||
|
|
||||||
pub struct TriggerRekey;
|
pub struct TriggerRekey;
|
||||||
@@ -12,7 +12,7 @@ impl Proposal for TriggerRekey {
|
|||||||
type Settings = ();
|
type Settings = ();
|
||||||
|
|
||||||
async fn insert(
|
async fn insert(
|
||||||
_proposal_id: i32,
|
_proposal_id: ProposalId,
|
||||||
_settings: &Self::Settings,
|
_settings: &Self::Settings,
|
||||||
_conn: &mut DatabaseConnection,
|
_conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<()> {
|
) -> QueryResult<()> {
|
||||||
@@ -20,7 +20,7 @@ impl Proposal for TriggerRekey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn load(
|
async fn load(
|
||||||
_proposal_id: i32,
|
_proposal_id: ProposalId,
|
||||||
_conn: &mut DatabaseConnection,
|
_conn: &mut DatabaseConnection,
|
||||||
) -> QueryResult<Self::Settings> {
|
) -> QueryResult<Self::Settings> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
actors::proposal_manager::{Error as ProposalError, VoteOutcome},
|
actors::proposal_manager::{Error as ProposalError, VoteOutcome},
|
||||||
|
db::models::{OperatorIdentityId, ProposalId},
|
||||||
db::proposal::{
|
db::proposal::{
|
||||||
ProposalKind, approve_sdk_client, grant_wallet_access, one_off_transaction,
|
ProposalKind, approve_sdk_client, grant_wallet_access, one_off_transaction,
|
||||||
persistent_grant, replace_operator,
|
persistent_grant, replace_operator,
|
||||||
@@ -62,7 +63,7 @@ async fn handle_create(
|
|||||||
}
|
}
|
||||||
Some(ProtoKind::ReplaceOperator(p)) => {
|
Some(ProtoKind::ReplaceOperator(p)) => {
|
||||||
ProposalKind::ReplaceOperator(replace_operator::Settings {
|
ProposalKind::ReplaceOperator(replace_operator::Settings {
|
||||||
old_operator_id: p.old_operator_id,
|
old_operator_id: OperatorIdentityId::from_raw(p.old_operator_id),
|
||||||
new_pubkey: p.new_pubkey,
|
new_pubkey: p.new_pubkey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,9 @@ async fn handle_create(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Some(wrap(GovResponsePayload::Created(
|
Ok(Some(wrap(GovResponsePayload::Created(
|
||||||
proto_gov::CreateProposalResponse { proposal_id },
|
proto_gov::CreateProposalResponse {
|
||||||
|
proposal_id: proposal_id.to_raw(),
|
||||||
|
},
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +198,7 @@ async fn handle_vote(
|
|||||||
) -> Result<Option<OperatorResponsePayload>, Status> {
|
) -> Result<Option<OperatorResponsePayload>, Status> {
|
||||||
let result = actor
|
let result = actor
|
||||||
.ask(HandleCastVote {
|
.ask(HandleCastVote {
|
||||||
proposal_id: req.proposal_id,
|
proposal_id: ProposalId::from_raw(req.proposal_id),
|
||||||
approve: req.approve,
|
approve: req.approve,
|
||||||
signature: req.signature,
|
signature: req.signature,
|
||||||
})
|
})
|
||||||
@@ -235,9 +238,9 @@ async fn handle_query(
|
|||||||
let proposals = summaries
|
let proposals = summaries
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| proto_gov::ProposalSummary {
|
.map(|s| proto_gov::ProposalSummary {
|
||||||
id: s.id,
|
id: s.id.to_raw(),
|
||||||
kind: <&'static str>::from(s.kind).to_owned(),
|
kind: <&'static str>::from(s.kind).to_owned(),
|
||||||
initiator_id: s.initiator_id,
|
initiator_id: s.initiator_id.to_raw(),
|
||||||
expires_at: s.expires_at.0.timestamp(),
|
expires_at: s.expires_at.0.timestamp(),
|
||||||
approve_count: s.approve_count,
|
approve_count: s.approve_count,
|
||||||
reject_count: s.reject_count,
|
reject_count: s.reject_count,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::{Error, OperatorSession};
|
use super::{Error, OperatorSession};
|
||||||
|
use crate::db::models::{OperatorIdentityId, ProposalId};
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::{
|
actors::{
|
||||||
evm::{
|
evm::{
|
||||||
@@ -287,9 +288,9 @@ impl OperatorSession {
|
|||||||
&mut self,
|
&mut self,
|
||||||
kind: crate::db::proposal::ProposalKind,
|
kind: crate::db::proposal::ProposalKind,
|
||||||
ttl_secs: Option<u32>,
|
ttl_secs: Option<u32>,
|
||||||
) -> Result<i32, Error> {
|
) -> Result<ProposalId, Error> {
|
||||||
use crate::actors::proposal_manager::CreateProposal;
|
use crate::actors::proposal_manager::CreateProposal;
|
||||||
let initiator_id = self.credentials.id;
|
let initiator_id = OperatorIdentityId::from_raw(self.credentials.id);
|
||||||
self.props
|
self.props
|
||||||
.actors
|
.actors
|
||||||
.proposal_manager
|
.proposal_manager
|
||||||
@@ -304,12 +305,12 @@ impl OperatorSession {
|
|||||||
#[message]
|
#[message]
|
||||||
pub(crate) async fn handle_cast_vote(
|
pub(crate) async fn handle_cast_vote(
|
||||||
&mut self,
|
&mut self,
|
||||||
proposal_id: i32,
|
proposal_id: ProposalId,
|
||||||
approve: bool,
|
approve: bool,
|
||||||
signature: Vec<u8>,
|
signature: Vec<u8>,
|
||||||
) -> Result<crate::actors::proposal_manager::VoteOutcome, crate::actors::proposal_manager::Error> {
|
) -> Result<crate::actors::proposal_manager::VoteOutcome, crate::actors::proposal_manager::Error> {
|
||||||
use crate::actors::proposal_manager::CastVote;
|
use crate::actors::proposal_manager::CastVote;
|
||||||
let operator_id = self.credentials.id;
|
let operator_id = OperatorIdentityId::from_raw(self.credentials.id);
|
||||||
self.props
|
self.props
|
||||||
.actors
|
.actors
|
||||||
.proposal_manager
|
.proposal_manager
|
||||||
@@ -326,7 +327,7 @@ impl OperatorSession {
|
|||||||
&mut self,
|
&mut self,
|
||||||
) -> Vec<crate::actors::proposal_manager::ProposalSummary> {
|
) -> Vec<crate::actors::proposal_manager::ProposalSummary> {
|
||||||
use crate::actors::proposal_manager::QueryPending;
|
use crate::actors::proposal_manager::QueryPending;
|
||||||
let operator_id = self.credentials.id;
|
let operator_id = OperatorIdentityId::from_raw(self.credentials.id);
|
||||||
self.props
|
self.props
|
||||||
.actors
|
.actors
|
||||||
.proposal_manager
|
.proposal_manager
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use arbiter_server::{
|
|||||||
crypto::KeyCell,
|
crypto::KeyCell,
|
||||||
db::{
|
db::{
|
||||||
self,
|
self,
|
||||||
|
models::{OperatorIdentityId, ProposalId, RecoveryOperatorIdentityId},
|
||||||
proposal::{
|
proposal::{
|
||||||
ProposalKind, approve_sdk_client, grant_wallet_access, one_off_transaction,
|
ProposalKind, approve_sdk_client, grant_wallet_access, one_off_transaction,
|
||||||
persistent_grant, replace_operator,
|
persistent_grant, replace_operator,
|
||||||
@@ -24,41 +25,45 @@ use arbiter_server::db::schema::{
|
|||||||
use diesel::{ExpressionMethods, QueryDsl, insert_into};
|
use diesel::{ExpressionMethods, QueryDsl, insert_into};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
async fn register_operator(db: &db::DatabasePool, pubkey: &authn::PublicKey) -> i32 {
|
async fn register_operator(db: &db::DatabasePool, pubkey: &authn::PublicKey) -> OperatorIdentityId {
|
||||||
let mut conn = db.get().await.unwrap();
|
let mut conn = db.get().await.unwrap();
|
||||||
insert_into(operator_identity::table)
|
insert_into(operator_identity::table)
|
||||||
.values(operator_identity::public_key.eq(pubkey.to_bytes()))
|
.values(operator_identity::public_key.eq(pubkey.to_bytes()))
|
||||||
.returning(operator_identity::id)
|
.returning(operator_identity::id)
|
||||||
.get_result::<i32>(&mut conn)
|
.get_result::<OperatorIdentityId>(&mut conn)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn register_recovery_operator(db: &db::DatabasePool, pubkey: &authn::PublicKey) -> i32 {
|
async fn register_recovery_operator(
|
||||||
|
db: &db::DatabasePool,
|
||||||
|
pubkey: &authn::PublicKey,
|
||||||
|
) -> RecoveryOperatorIdentityId {
|
||||||
let mut conn = db.get().await.unwrap();
|
let mut conn = db.get().await.unwrap();
|
||||||
insert_into(recovery_operator_identity::table)
|
insert_into(recovery_operator_identity::table)
|
||||||
.values(recovery_operator_identity::public_key.eq(pubkey.to_bytes()))
|
.values(recovery_operator_identity::public_key.eq(pubkey.to_bytes()))
|
||||||
.returning(recovery_operator_identity::id)
|
.returning(recovery_operator_identity::id)
|
||||||
.get_result::<i32>(&mut conn)
|
.get_result::<RecoveryOperatorIdentityId>(&mut conn)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Backdates a wakeup request so it appears to have passed the 14-day window.
|
/// Backdates a wakeup request so it appears to have passed the 14-day window.
|
||||||
async fn insert_active_wakeup(db: &db::DatabasePool, operator_id: i32) {
|
async fn insert_active_wakeup(db: &db::DatabasePool, operator_id: OperatorIdentityId) {
|
||||||
let mut conn = db.get().await.unwrap();
|
let mut conn = db.get().await.unwrap();
|
||||||
diesel::sql_query(format!(
|
diesel::sql_query(format!(
|
||||||
"INSERT INTO recovery_wakeup_request (requested_by, requested_at) \
|
"INSERT INTO recovery_wakeup_request (requested_by, requested_at) \
|
||||||
VALUES ({operator_id}, unixepoch('now') - 14*24*3600 - 1)"
|
VALUES ({}, unixepoch('now') - 14*24*3600 - 1)",
|
||||||
|
operator_id.to_raw()
|
||||||
))
|
))
|
||||||
.execute(&mut conn)
|
.execute(&mut conn)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_vote_message(proposal_id: i32, approve: bool) -> Vec<u8> {
|
fn make_vote_message(proposal_id: ProposalId, approve: bool) -> Vec<u8> {
|
||||||
let mut msg = Vec::with_capacity(9);
|
let mut msg = Vec::with_capacity(9);
|
||||||
msg.extend_from_slice(&(proposal_id as i64).to_be_bytes());
|
msg.extend_from_slice(&i64::from(proposal_id.to_raw()).to_be_bytes());
|
||||||
msg.push(u8::from(approve));
|
msg.push(u8::from(approve));
|
||||||
msg
|
msg
|
||||||
}
|
}
|
||||||
@@ -128,13 +133,13 @@ async fn create_proposal_returns_id() {
|
|||||||
.proposal_manager
|
.proposal_manager
|
||||||
.ask(CreateProposal {
|
.ask(CreateProposal {
|
||||||
kind: ProposalKind::ApproveSdkClient(approve_sdk_client::Settings { client_id: 42 }),
|
kind: ProposalKind::ApproveSdkClient(approve_sdk_client::Settings { client_id: 42 }),
|
||||||
initiator_id: 1,
|
initiator_id: OperatorIdentityId::from_raw(1),
|
||||||
ttl_secs: None,
|
ttl_secs: None,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(proposal_id > 0);
|
assert!(proposal_id.to_raw() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@@ -935,7 +940,7 @@ async fn key_rotation_requires_full_quorum() {
|
|||||||
.proposal_manager
|
.proposal_manager
|
||||||
.ask(CreateProposal {
|
.ask(CreateProposal {
|
||||||
kind: ProposalKind::ReplaceOperator(replace_operator::Settings {
|
kind: ProposalKind::ReplaceOperator(replace_operator::Settings {
|
||||||
old_operator_id: 1,
|
old_operator_id: OperatorIdentityId::from_raw(1),
|
||||||
new_pubkey,
|
new_pubkey,
|
||||||
}),
|
}),
|
||||||
initiator_id: op1,
|
initiator_id: op1,
|
||||||
@@ -983,7 +988,7 @@ async fn recovery_vote_rejected_when_sleeping() {
|
|||||||
.proposal_manager
|
.proposal_manager
|
||||||
.ask(CreateProposal {
|
.ask(CreateProposal {
|
||||||
kind: ProposalKind::ReplaceOperator(replace_operator::Settings {
|
kind: ProposalKind::ReplaceOperator(replace_operator::Settings {
|
||||||
old_operator_id: 1,
|
old_operator_id: OperatorIdentityId::from_raw(1),
|
||||||
new_pubkey,
|
new_pubkey,
|
||||||
}),
|
}),
|
||||||
initiator_id: op_id,
|
initiator_id: op_id,
|
||||||
@@ -1137,7 +1142,7 @@ async fn recovery_operator_vote_contributes_to_replace_quorum() {
|
|||||||
.proposal_manager
|
.proposal_manager
|
||||||
.ask(CreateProposal {
|
.ask(CreateProposal {
|
||||||
kind: ProposalKind::ReplaceOperator(replace_operator::Settings {
|
kind: ProposalKind::ReplaceOperator(replace_operator::Settings {
|
||||||
old_operator_id: 1,
|
old_operator_id: OperatorIdentityId::from_raw(1),
|
||||||
new_pubkey,
|
new_pubkey,
|
||||||
}),
|
}),
|
||||||
initiator_id: op_id,
|
initiator_id: op_id,
|
||||||
|
|||||||
Reference in New Issue
Block a user