mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 07:11:36 +02:00
move sender nonce handling
This commit is contained in:
@@ -44,7 +44,6 @@ without a user confirmation step.
|
||||
- Add a Grin node API for kernel lookup by MMR index, then use the witness index instead
|
||||
of searching by commitment.
|
||||
- Expose the kernel feature constants from `grin_core` and reuse them here.
|
||||
- Make sender-nonce commitment handling reusable outside contracts
|
||||
- Add compact Slatepack support for contracts
|
||||
- Keep Slate V5 experimental until the related RFCs are accepted
|
||||
- Add contract history, lookup and transport.
|
||||
@@ -52,6 +51,8 @@ without a user confirmation step.
|
||||
- Store transactions in LMDB so they can be committed with the wallet state.
|
||||
- Revisit automatic receive signing once there is a user confirmation step.
|
||||
- Revisit `remove_other_sigdata` before allowing more than two participants.
|
||||
- Check all preserved slate fields in the round-trip tests
|
||||
- Test a full MWixnet round with a received contract output
|
||||
|
||||
### Side-effects
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
use crate::backend::WalletBackend;
|
||||
use crate::contract::types::ProofArgs;
|
||||
use crate::grin_keychain::Keychain;
|
||||
use crate::grin_util::secp::key::{PublicKey, SecretKey};
|
||||
use crate::grin_util::secp::key::SecretKey;
|
||||
use crate::grin_util::secp::Secp256k1;
|
||||
use crate::payment_proof::{sender_nonce_tweak, EarlyPaymentProof};
|
||||
use crate::payment_proof::EarlyPaymentProof;
|
||||
use crate::slate::{PaymentProofType, Slate};
|
||||
use crate::types::{Context, NodeClient};
|
||||
use crate::{address, Error};
|
||||
@@ -46,22 +46,11 @@ pub(super) fn commit_sender_nonce(
|
||||
.sender_address
|
||||
.ok_or(Error::NoSenderAddressProvided)?;
|
||||
let proof = EarlyPaymentProof::from_slate(slate, 0, Some(sender_address))?;
|
||||
if let Some(base_public) = context.sender_public_nonce.as_ref() {
|
||||
let mut expected = base_public.clone();
|
||||
expected.add_exp_assign(secp, &sender_nonce_tweak(secp, base_public, &proof)?)?;
|
||||
if PublicKey::from_secret_key(secp, &context.sec_nonce)? != expected {
|
||||
return Err(Error::PaymentProofValidation(
|
||||
"Sender nonce proof details changed".into(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
let base_public = PublicKey::from_secret_key(secp, &context.sec_nonce)?;
|
||||
context
|
||||
.sec_nonce
|
||||
.add_assign(secp, &sender_nonce_tweak(secp, &base_public, &proof)?)?;
|
||||
context.sender_public_nonce = Some(base_public);
|
||||
}
|
||||
Ok(())
|
||||
proof.commit_sender_nonce(
|
||||
secp,
|
||||
&mut context.sec_nonce,
|
||||
&mut context.sender_public_nonce,
|
||||
)
|
||||
}
|
||||
|
||||
/// Add the receiver's proof data to a contract slate.
|
||||
|
||||
@@ -279,6 +279,37 @@ impl EarlyPaymentProof {
|
||||
Ok(proof)
|
||||
}
|
||||
|
||||
/// Commit the sender nonce before sharing its public value
|
||||
/// Save the base nonce on the first call and verify it on retries
|
||||
pub fn commit_sender_nonce(
|
||||
&self,
|
||||
secp: &Secp256k1,
|
||||
secret_nonce: &mut SecretKey,
|
||||
base_public_nonce: &mut Option<PublicKey>,
|
||||
) -> Result<(), Error> {
|
||||
if self.proof_type != PaymentProofType::SenderNonce {
|
||||
return Err(Error::PaymentProofValidation(
|
||||
"Sender nonce commitment requires a sender-nonce proof".into(),
|
||||
));
|
||||
}
|
||||
if let Some(base_public) = base_public_nonce.as_ref() {
|
||||
let mut expected = base_public.clone();
|
||||
expected.add_exp_assign(secp, &sender_nonce_tweak(secp, base_public, self)?)?;
|
||||
if PublicKey::from_secret_key(secp, secret_nonce)? != expected {
|
||||
return Err(Error::PaymentProofValidation(
|
||||
"Sender nonce proof details changed".into(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
let base_public = PublicKey::from_secret_key(secp, secret_nonce)?;
|
||||
let mut committed_nonce = secret_nonce.clone();
|
||||
committed_nonce.add_assign(secp, &sender_nonce_tweak(secp, &base_public, self)?)?;
|
||||
*secret_nonce = committed_nonce;
|
||||
*base_public_nonce = Some(base_public);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sign the payment promise
|
||||
pub fn sign(&self, sec_key: &SecretKey) -> Result<(DalekSignature, DalekPublicKey), Error> {
|
||||
let d_skey = DalekSecretKey::from_bytes(&sec_key.0);
|
||||
@@ -403,7 +434,7 @@ impl EarlyPaymentProof {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sender_nonce_tweak(
|
||||
fn sender_nonce_tweak(
|
||||
secp: &Secp256k1,
|
||||
sender_nonce: &PublicKey,
|
||||
proof: &EarlyPaymentProof,
|
||||
@@ -644,6 +675,21 @@ mod tests {
|
||||
sender_nonce_tweak(&secp, &base, &sender_nonce)?.0.to_hex(),
|
||||
"6bd7c4e86bd61999c26fdd4cc1af90cdcb0a79e39644f4d8045e2a6599bd4db0"
|
||||
);
|
||||
let mut secret_nonce = SecretKey::from_slice(&secp, &[9; 32])?;
|
||||
let mut public_nonce = None;
|
||||
assert!(proof
|
||||
.commit_sender_nonce(&secp, &mut secret_nonce, &mut public_nonce)
|
||||
.is_err());
|
||||
sender_nonce.commit_sender_nonce(&secp, &mut secret_nonce, &mut public_nonce)?;
|
||||
assert_eq!(public_nonce, Some(base));
|
||||
let committed_nonce = secret_nonce.clone();
|
||||
sender_nonce.commit_sender_nonce(&secp, &mut secret_nonce, &mut public_nonce)?;
|
||||
assert_eq!(secret_nonce, committed_nonce);
|
||||
let mut changed = sender_nonce.clone();
|
||||
changed.memo = Some(PaymentMemo::new("changed details".into())?);
|
||||
assert!(changed
|
||||
.commit_sender_nonce(&secp, &mut secret_nonce, &mut public_nonce)
|
||||
.is_err());
|
||||
let (signature, recipient) = sender_nonce.sign(&proof_key)?;
|
||||
sender_nonce.promise_signature = Some(signature);
|
||||
sender_nonce.amount += 1;
|
||||
|
||||
Reference in New Issue
Block a user