Skip to content

Commit

Permalink
Tests and wasm bindings for SignedTransactionIntent; some renaming an…
Browse files Browse the repository at this point in the history
…d cleanup
  • Loading branch information
ImplOfAnImpl committed Oct 31, 2024
1 parent 20de725 commit 617abcf
Show file tree
Hide file tree
Showing 18 changed files with 759 additions and 137 deletions.
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions api-server/scanner-lib/src/sync/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,8 @@ async fn reorg_locked_balance(#[case] seed: Seed) {
idx,
)
.unwrap();
let signature = sign_public_key_spending(&priv_key, &pub_key, &sighash, &mut rng).unwrap();
let signature =
sign_public_key_spending(&priv_key, &pub_key, &sighash, &mut rng).unwrap();
InputWitness::Standard(StandardInputSignature::new(
SigHashType::default(),
signature.encode(),
Expand Down Expand Up @@ -867,7 +868,8 @@ async fn reorg_locked_balance(#[case] seed: Seed) {
idx,
)
.unwrap();
let signature = sign_public_key_spending(&priv_key, &pub_key, &sighash, &mut rng).unwrap();
let signature =
sign_public_key_spending(&priv_key, &pub_key, &sighash, &mut rng).unwrap();
InputWitness::Standard(StandardInputSignature::new(
SigHashType::default(),
signature.encode(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const MESSAGE_MAGIC_SUFFIX: &str = "\n===MINTLAYER MESSAGE END===";
use randomness::{CryptoRng, Rng};
use thiserror::Error;

use serialization::{Decode, Encode};
use serialization::Encode;

use crate::{
chain::{signature::DestinationSigError, ChainConfig, Destination},
Expand All @@ -31,7 +31,8 @@ use super::{
sign_public_key_spending, verify_public_key_spending, AuthorizedPublicKeySpend,
},
authorize_pubkeyhash_spend::{
sign_public_key_hash_spending, verify_public_key_hash_spending, AuthorizedPublicKeyHashSpend,
sign_public_key_hash_spending, sign_public_key_hash_spending_unchecked,
verify_public_key_hash_spending, AuthorizedPublicKeyHashSpend,
},
classical_multisig::authorize_classical_multisig::{
verify_classical_multisig_spending, AuthorizedClassicalMultisigSpend,
Expand All @@ -50,7 +51,7 @@ pub enum SignArbitraryMessageError {
Unsupported,
}

#[derive(Debug, Clone, Eq, Encode, Decode, PartialEq)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ArbitraryMessageSignature {
raw_signature: Vec<u8>,
}
Expand Down Expand Up @@ -148,6 +149,20 @@ impl ArbitraryMessageSignature {
raw_signature: signature,
})
}

pub fn produce_uniparty_signature_as_pub_key_hash_spending<R: Rng + CryptoRng>(
private_key: &crypto::key::PrivateKey,
message: &[u8],
rng: R,
) -> Result<Self, SignArbitraryMessageError> {
let challenge = produce_message_challenge(message);
let signature = sign_public_key_hash_spending_unchecked(private_key, &challenge, rng)?;
let signature = signature.encode();

Ok(Self {
raw_signature: signature,
})
}
}

#[cfg(test)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,46 @@ fn sign_verify_supported_destinations(#[case] seed: Seed) {
}
}

// Check that `produce_uniparty_signature_as_pub_key_hash_spending` gives the same result as
// `produce_uniparty_signature` does for `Destination::PublicKeyHash`.
#[rstest]
#[trace]
#[case(Seed::from_entropy())]
fn produce_uniparty_signature_as_pub_key_hash_spending_matches_produce_uniparty_signature(
#[case] seed: Seed,
) {
let mut rng = test_utils::random::make_seedable_rng(seed);

let chain_config = chain::config::create_testnet();

let (private_key, public_key) = PrivateKey::new_from_rng(&mut rng, KeyKind::Secp256k1Schnorr);
let message: Vec<u8> = (20..40).map(|_| rng.gen()).collect();
let message_challenge = produce_message_challenge(&message);

let destination_addr = Destination::PublicKeyHash(PublicKeyHash::from(&public_key));
// Use the identical rng for both of the signer calls to be able to compare the signatures.
let signer_rng_seed = rng.gen();

let sig1 = ArbitraryMessageSignature::produce_uniparty_signature(
&private_key,
&destination_addr,
&message,
test_utils::random::make_seedable_rng(signer_rng_seed),
)
.unwrap();
sig1.verify_signature(&chain_config, &destination_addr, &message_challenge)
.unwrap();

let sig2 = ArbitraryMessageSignature::produce_uniparty_signature_as_pub_key_hash_spending(
&private_key,
&message,
test_utils::random::make_seedable_rng(signer_rng_seed),
)
.unwrap();

assert_eq!(sig1, sig2);
}

// Try to sign and verify using a destination that is unsupported for signing and/or verification.
// Specific errors should be produced in each case.
#[rstest]
Expand Down Expand Up @@ -308,7 +348,7 @@ fn verify_corrupted_signature(#[case] seed: Seed) {
// 1) Construct a message containing tx data that would normally be hashed when signing
// a transaction.
// 2) As a sanity check, hash the message and use one of the "standard" functions
// (sign_pubkey_spending) to produce a tx signature; check that the signature is indeed correct.
// (sign_public_key_spending) to produce a tx signature; check that the signature is indeed correct.
// 3) Sign the message via SignedArbitraryMessage::produce_uniparty_signature; check that the
// result is NOT a valid transaction signature.
#[rstest]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ mod test {
#[rstest]
#[trace]
#[case(Seed::from_entropy())]
fn test_sign_pubkey_spending(#[case] seed: Seed) {
fn test_sign_public_key_spending(#[case] seed: Seed) {
let mut rng = test_utils::random::make_seedable_rng(seed);

let (private_key, public_key) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crypto::key::{PublicKey, Signature};
use crypto::key::{PrivateKey, PublicKey, Signature};
use randomness::{CryptoRng, Rng};
use serialization::{Decode, DecodeAll, Encode};

Expand Down Expand Up @@ -69,6 +69,26 @@ pub fn sign_public_key_hash_spending<R: Rng + CryptoRng>(
if calculated_addr != *spendee_addr {
return Err(DestinationSigError::PublicKeyToAddressMismatch);
}
sign_public_key_hash_spending_impl(&private_key, public_key, sighash, rng)
}

pub fn sign_public_key_hash_spending_unchecked<R: Rng + CryptoRng>(
private_key: &crypto::key::PrivateKey,
sighash: &H256,
rng: R,
) -> Result<AuthorizedPublicKeyHashSpend, DestinationSigError> {
let public_key = PublicKey::from_private_key(private_key);
sign_public_key_hash_spending_impl(&private_key, public_key, sighash, rng)
}

fn sign_public_key_hash_spending_impl<R: Rng + CryptoRng>(
private_key: &PrivateKey,
public_key: PublicKey,
sighash: &H256,
rng: R,
) -> Result<AuthorizedPublicKeyHashSpend, DestinationSigError> {
debug_assert_eq!(public_key, PublicKey::from_private_key(private_key));

let msg = sighash.encode();
let signature = private_key
.sign_message(&msg, rng)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ use super::{
sign_public_key_spending, verify_public_key_spending, AuthorizedPublicKeySpend,
},
authorize_pubkeyhash_spend::{
sign_public_key_hash_spending, verify_public_key_hash_spending, AuthorizedPublicKeyHashSpend,
sign_public_key_hash_spending, verify_public_key_hash_spending,
AuthorizedPublicKeyHashSpend,
},
classical_multisig::{
authorize_classical_multisig::{
Expand Down Expand Up @@ -143,6 +144,8 @@ impl StandardInputSignature {
inputs_utxos: &[Option<&TxOutput>],
input_num: usize,
) -> Result<Self, DestinationSigError> {
use super::classical_multisig::multisig_partial_signature::SigsVerifyResult;

let sighash = signature_hash(sighash_type, tx, inputs_utxos, input_num)?;
let message = sighash.encode();

Expand All @@ -152,9 +155,13 @@ impl StandardInputSignature {
let verification_result = verifier.verify_signatures(chain_config)?;

match verification_result {
super::classical_multisig::multisig_partial_signature::SigsVerifyResult::CompleteAndValid => (),
super::classical_multisig::multisig_partial_signature::SigsVerifyResult::Incomplete => return Err(DestinationSigError::IncompleteClassicalMultisigAuthorization),
super::classical_multisig::multisig_partial_signature::SigsVerifyResult::Invalid => return Err(DestinationSigError::InvalidClassicalMultisigAuthorization),
SigsVerifyResult::CompleteAndValid => (),
SigsVerifyResult::Incomplete => {
return Err(DestinationSigError::IncompleteClassicalMultisigAuthorization)
}
SigsVerifyResult::Invalid => {
return Err(DestinationSigError::InvalidClassicalMultisigAuthorization)
}
}

let serialized_sig = authorization.encode();
Expand Down
4 changes: 2 additions & 2 deletions common/src/chain/transaction/signature/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ pub enum DestinationSigError {
SignatureVerificationWithoutSigs,
#[error("Input corresponding to output number {0} does not exist (number of inputs is {1})")]
InvalidOutputIndexForModeSingle(usize, usize),
#[error("Decoding witness failed ")]
#[error("Decoding witness failed")]
DecodingWitnessFailed,
#[error("Signature verification failed ")]
#[error("Signature verification failed")]
SignatureVerificationFailed,
#[error("Public key to address mismatch")]
PublicKeyToAddressMismatch,
Expand Down
Loading

0 comments on commit 617abcf

Please sign in to comment.