mirror of
https://github.com/serai-dex/serai.git
synced 2025-02-02 19:26:26 +00:00
Error when the wrong spend key is used to sign a transaction
Moves decoy selection to being the last step in the multisig process so the RPC is only polled to continue valid transactions.
This commit is contained in:
parent
27751d8d98
commit
d611300adb
2 changed files with 33 additions and 20 deletions
|
@ -87,6 +87,8 @@ pub enum TransactionError {
|
|||
NotEnoughFunds(u64, u64),
|
||||
#[error("invalid address")]
|
||||
InvalidAddress,
|
||||
#[error("wrong spend private key")]
|
||||
WrongPrivateKey,
|
||||
#[error("rpc error ({0})")]
|
||||
RpcError(RpcError),
|
||||
#[error("clsag error ({0})")]
|
||||
|
@ -282,7 +284,12 @@ impl SignableTransaction {
|
|||
) -> Result<Transaction, TransactionError> {
|
||||
let mut images = Vec::with_capacity(self.inputs.len());
|
||||
for input in &self.inputs {
|
||||
images.push(generate_key_image(&(spend + input.key_offset)));
|
||||
let offset = spend + input.key_offset;
|
||||
if (&offset * &ED25519_BASEPOINT_TABLE) != input.key {
|
||||
Err(TransactionError::WrongPrivateKey)?;
|
||||
}
|
||||
|
||||
images.push(generate_key_image(&offset));
|
||||
}
|
||||
images.sort_by(key_image_sort);
|
||||
|
||||
|
|
|
@ -83,6 +83,31 @@ impl SignableTransaction {
|
|||
}
|
||||
transcript.append_message(b"change", &self.change.as_bytes());
|
||||
|
||||
// Sort included before cloning it around
|
||||
included.sort_unstable();
|
||||
|
||||
for (i, input) in self.inputs.iter().enumerate() {
|
||||
// Check this the right set of keys
|
||||
let offset = keys.offset(dalek_ff_group::Scalar(input.key_offset));
|
||||
if offset.group_key().0 != input.key {
|
||||
Err(TransactionError::WrongPrivateKey)?;
|
||||
}
|
||||
|
||||
clsags.push(
|
||||
AlgorithmMachine::new(
|
||||
ClsagMultisig::new(
|
||||
transcript.clone(),
|
||||
inputs[i].clone()
|
||||
).map_err(|e| TransactionError::MultisigError(e))?,
|
||||
Arc::new(offset),
|
||||
&included
|
||||
).map_err(|e| TransactionError::FrostError(e))?
|
||||
);
|
||||
}
|
||||
|
||||
// Verify these outputs by a dummy prep
|
||||
self.prepare_outputs(rng, [0; 32])?;
|
||||
|
||||
// Select decoys
|
||||
// Ideally, this would be done post entropy, instead of now, yet doing so would require sign
|
||||
// to be async which isn't preferable. This should be suitably competent though
|
||||
|
@ -97,25 +122,6 @@ impl SignableTransaction {
|
|||
&self.inputs
|
||||
).await.map_err(|e| TransactionError::RpcError(e))?;
|
||||
|
||||
// Sort included before cloning it around
|
||||
included.sort_unstable();
|
||||
|
||||
for (i, input) in self.inputs.iter().enumerate() {
|
||||
clsags.push(
|
||||
AlgorithmMachine::new(
|
||||
ClsagMultisig::new(
|
||||
transcript.clone(),
|
||||
inputs[i].clone()
|
||||
).map_err(|e| TransactionError::MultisigError(e))?,
|
||||
Arc::new(keys.offset(dalek_ff_group::Scalar(input.key_offset))),
|
||||
&included
|
||||
).map_err(|e| TransactionError::FrostError(e))?
|
||||
);
|
||||
}
|
||||
|
||||
// Verify these outputs by a dummy prep
|
||||
self.prepare_outputs(rng, [0; 32])?;
|
||||
|
||||
Ok(TransactionMachine {
|
||||
signable: self,
|
||||
i: keys.params().i(),
|
||||
|
|
Loading…
Reference in a new issue