Skip to content

Commit

Permalink
test(pactus): add compiler and signer tests
Browse files Browse the repository at this point in the history
  • Loading branch information
b00f committed Oct 9, 2024
1 parent e288bb7 commit b4fb941
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 72 deletions.
2 changes: 0 additions & 2 deletions rust/chains/tw_pactus/rustfmt.toml

This file was deleted.

12 changes: 6 additions & 6 deletions rust/chains/tw_pactus/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
//
// Copyright © 2017 Trust Wallet.

use std::borrow::Cow;

use tw_coin_entry::coin_context::CoinContext;
use tw_coin_entry::coin_entry::{PublicKeyBytes, SignatureBytes};
use tw_coin_entry::error::prelude::*;
Expand Down Expand Up @@ -31,11 +29,11 @@ impl PactusCompiler {
input: Proto::SigningInput<'_>,
) -> SigningResult<CompilerProto::PreSigningOutput<'static>> {
let trx = Transaction::from_proto(&input)?;
let data = trx.to_bytes()?;
let sign_bytes = trx.sign_bytes()?;

let output = CompilerProto::PreSigningOutput {
data_hash: Cow::Owned(trx.id()),
data: data.into(),
data_hash: trx.id().into(),
data: sign_bytes.into(),
..CompilerProto::PreSigningOutput::default()
};

Expand Down Expand Up @@ -75,7 +73,9 @@ impl PactusCompiler {
let data = trx.to_bytes()?;

let output = Proto::SigningOutput {
encoded: data.into(),
transaction_id: trx.id().into(),
signed_transaction_data: data.into(),
signature: signature.to_bytes().to_vec().into(),
..Proto::SigningOutput::default()
};

Expand Down
6 changes: 4 additions & 2 deletions rust/chains/tw_pactus/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ impl PactusSigner {
) -> SigningResult<Proto::SigningOutput<'static>> {
let mut trx = Transaction::from_proto(&input)?;
let key_pair = ed25519::sha512::KeyPair::try_from(input.private_key.as_ref())?;
trx.sign(key_pair.private())?;
let signature = trx.sign(key_pair.private())?;

let data = trx.to_bytes()?;

let output = Proto::SigningOutput {
encoded: data.into(),
transaction_id: trx.id().into(),
signed_transaction_data: data.into(),
signature: signature.to_bytes().to_vec().into(),
..Proto::SigningOutput::default()
};

Expand Down
56 changes: 28 additions & 28 deletions rust/chains/tw_pactus/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,13 @@ impl Transaction {
Ok(deserialize::<Transaction>(input)?)
}

pub fn sign(&mut self, private_key: &PrivateKey) -> SigningResult<()> {
pub fn sign(&mut self, private_key: &PrivateKey) -> SigningResult<Signature> {
let sign_bytes = self.sign_bytes()?;
let signature = private_key.sign(sign_bytes)?;

self.set_signatory(private_key.public(), signature);
self.set_signatory(private_key.public(), signature.clone());

Ok(())
Ok(signature)
}

pub fn set_signatory(&mut self, public_key: PublicKey, signature: Signature) {
Expand All @@ -213,7 +213,7 @@ impl Transaction {
Ok(w.to_vec())
}

fn sign_bytes(&self) -> SigningResult<Vec<u8>> {
pub fn sign_bytes(&self) -> SigningResult<Vec<u8>> {
let mut w = Vec::new();
self.encode_with_no_signatory(&mut w)?;
let mut sign_bytes = w.to_vec();
Expand Down Expand Up @@ -321,52 +321,52 @@ mod tests {
assert_eq!(stream.to_vec(), &[4]);
}

const DATA_HEX_NOT_SIGNED: &str = concat!(
const TRANSACTION_NOT_SIGNED: &str = concat!(
"02", // Flags
"01", // Version
"01020304", // LockTime
"01", // Fee
"01020300", // LockTime
"e807", // Fee
"0474657374", // Memo
"01", // PayloadType
"033333333333333333333333333333333333333333", // Sender
"032222222222222222222222222222222222222222", // Receiver
"02"
); // Amount
"037098338e0b6808119dfd4457ab806b9c2059b89b", // Sender
"037a14ae24533816e7faaa6ed28fcdde8e55a7df21", // Receiver
"a09c01" // Amount
);

const DATA_HEX_SIGNED: &str = concat!(
const TRANSACTION_SIGNED: &str = concat!(
"00", // Flags
"01", // Version
"01020304", // LockTime
"01", // Fee
"01020300", // LockTime
"e807", // Fee
"0474657374", // Memo
"01", // PayloadType
"033333333333333333333333333333333333333333", // Sender
"032222222222222222222222222222222222222222", // Receiver
"02", // Amount
"5bf1420418b7aec8f2a28e9c90f1c346ca8b28134e2cf983e6f541350da6774f", // Signature
"033aa2c42f12a5fa95be506c790e99731a9b5b9989e7b37bc192c642331d9c09",
"037098338e0b6808119dfd4457ab806b9c2059b89b", // Sender
"037a14ae24533816e7faaa6ed28fcdde8e55a7df21", // Receiver
"a09c01", // Amount
"50ac25c7125271489b0cd230549257c93fb8c6265f2914a988ba7b81c1bc47ff", // Signature
"f027412dd59447867911035ff69742d171060a1f132ac38b95acc6e39ec0bd09",
"95794161374b22c696dabb98e93f6ca9300b22f3b904921fbf560bb72145f4fa" // PublicKey
);

const TX_ID: &str = "e5a0e1fb4ee6f26a867dd3c091fc9fdfcbd25a5caff8cf13a4485a716501150d";
const TX_ID: &str = "34cd4656a98f7eb996e83efdc384cefbe3a9c52dca79a99245b4eacc0b0b4311";

#[test]
fn test_sign_signature() {
let expected_data = DATA_HEX_SIGNED.decode_hex().unwrap();
let expected_data = TRANSACTION_SIGNED.decode_hex().unwrap();
let expected_id = TX_ID.decode_hex().unwrap();

let sender = Address::from_str("pc1rxvenxvenxvenxvenxvenxvenxvenxvenupgaeg").unwrap();
let receiver = Address::from_str("pc1ryg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zwllqv6").unwrap();
let sender = Address::from_str("pc1rwzvr8rstdqypr80ag3t6hqrtnss9nwymcxy3lr").unwrap();
let receiver = Address::from_str("pc1r0g22ufzn8qtw0742dmfglnw73e260hep0k3yra").unwrap();
let payload = Box::new(TransferPayload {
sender,
receiver,
amount: Amount(2),
amount: Amount(20000),
});
let mut trx = Transaction::new(
FLAG_NOT_SIGNED,
VERSION_LATEST,
0x04030201,
Amount(1),
0x00030201,
Amount(1000),
"test".to_string(),
payload,
);
Expand All @@ -383,7 +383,7 @@ mod tests {

#[test]
fn test_encoding_not_signed() {
let data = DATA_HEX_NOT_SIGNED.decode_hex().unwrap();
let data = TRANSACTION_NOT_SIGNED.decode_hex().unwrap();
let trx = Transaction::from_bytes(&data).unwrap();
let expected_id = TX_ID.decode_hex().unwrap();

Expand All @@ -397,7 +397,7 @@ mod tests {

#[test]
fn test_encoding_signed() {
let data = DATA_HEX_SIGNED.decode_hex().unwrap();
let data = TRANSACTION_SIGNED.decode_hex().unwrap();
let trx = Transaction::from_bytes(&data).unwrap();
let expected_id = TX_ID.decode_hex().unwrap();

Expand Down
2 changes: 2 additions & 0 deletions rust/tw_tests/tests/chains/pactus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
mod pactus_address;
mod pactus_compile;
mod pactus_sign;
mod pactus_transaction_util;
mod test_cases;
75 changes: 74 additions & 1 deletion rust/tw_tests/tests/chains/pactus/pactus_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,80 @@
//
// Copyright © 2017 Trust Wallet.

use crate::chains::pactus::test_cases::transfer_1::{
pactus_sign_transfer_input, PRIVATE_KEY, SIGNATURE, SIGN_BYTES, TRANSACTION_SIGNED_DATA, TX_ID,
};
use tw_any_coin::ffi::tw_transaction_compiler::{
tw_transaction_compiler_compile, tw_transaction_compiler_pre_image_hashes,
};
use tw_coin_entry::error::prelude::*;
use tw_coin_registry::coin_type::CoinType;
use tw_encoding::hex::ToHex;
use tw_keypair::ed25519;
use tw_keypair::traits::{KeyPairTrait, SigningKeyTrait};
use tw_memory::test_utils::tw_data_helper::TWDataHelper;
use tw_memory::test_utils::tw_data_vector_helper::TWDataVectorHelper;
use tw_misc::traits::ToBytesVec;
use tw_proto::Pactus::Proto;
use tw_proto::TxCompiler::Proto as CompilerProto;
use tw_proto::{deserialize, serialize};

#[test]
fn test_pactus_compile() {
todo!()
// Step 1: Create signing input.
let input = pactus_sign_transfer_input();

// Step 2: Obtain preimage hash
let input_data = TWDataHelper::create(serialize(&input).unwrap());
let preimage_data = TWDataHelper::wrap(unsafe {
tw_transaction_compiler_pre_image_hashes(CoinType::Pactus as u32, input_data.ptr())
})
.to_vec()
.expect("!tw_transaction_compiler_pre_image_hashes returned nullptr");

let preimage: CompilerProto::PreSigningOutput =
deserialize(&preimage_data).expect("Coin entry returned an invalid output");

assert_eq!(preimage.error, SigningErrorType::OK);
assert!(preimage.error_message.is_empty());
assert_eq!(preimage.data.to_hex(), SIGN_BYTES);

// Step 3: Sign the data "externally"
let private_key = ed25519::sha512::KeyPair::try_from(PRIVATE_KEY).unwrap();
let public_key = private_key.public().to_vec();

let signature = private_key
.sign(preimage.data.to_vec())
.expect("Error signing data")
.to_vec();
assert_eq!(signature.to_hex(), SIGNATURE);

// Step 4: Compile transaction info

let signatures = TWDataVectorHelper::create([signature]);
let public_keys = TWDataVectorHelper::create([public_key]);

let input_data = TWDataHelper::create(serialize(&input).unwrap());
let output_data = TWDataHelper::wrap(unsafe {
tw_transaction_compiler_compile(
CoinType::Pactus as u32,
input_data.ptr(),
signatures.ptr(),
public_keys.ptr(),
)
})
.to_vec()
.expect("!tw_transaction_compiler_compile returned nullptr");

let output: Proto::SigningOutput =
deserialize(&output_data).expect("Coin entry returned an invalid output");

assert_eq!(output.error, SigningErrorType::OK);
assert!(output.error_message.is_empty());
assert_eq!(output.transaction_id.to_hex(), TX_ID);
assert_eq!(output.signature.to_hex(), SIGNATURE);
assert_eq!(
output.signed_transaction_data.to_hex(),
TRANSACTION_SIGNED_DATA
);
}
35 changes: 34 additions & 1 deletion rust/tw_tests/tests/chains/pactus/pactus_sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,40 @@
//
// Copyright © 2017 Trust Wallet.

use crate::chains::pactus::test_cases::transfer_1::{
pactus_sign_transfer_input, PRIVATE_KEY, SIGNATURE, TRANSACTION_SIGNED_DATA, TX_ID,
};
use tw_any_coin::ffi::tw_any_signer::tw_any_signer_sign;
use tw_coin_entry::error::prelude::*;
use tw_coin_registry::coin_type::CoinType;
use tw_encoding::hex::{DecodeHex, ToHex};
use tw_memory::test_utils::tw_data_helper::TWDataHelper;
use tw_proto::Pactus::Proto;
use tw_proto::{deserialize, serialize};

#[test]
fn test_pactus_sign() {
todo!()
let input = Proto::SigningInput {
private_key: PRIVATE_KEY.decode_hex().unwrap().into(),
..pactus_sign_transfer_input()
};

let input_data = TWDataHelper::create(serialize(&input).unwrap());

let output = TWDataHelper::wrap(unsafe {
tw_any_signer_sign(input_data.ptr(), CoinType::Pactus as u32)
})
.to_vec()
.expect("!tw_any_signer_sign returned nullptr");

let output: Proto::SigningOutput = deserialize(&output).unwrap();

assert_eq!(output.error, SigningErrorType::OK);
assert!(output.error_message.is_empty());
assert_eq!(output.transaction_id.to_hex(), TX_ID);
assert_eq!(output.signature.to_hex(), SIGNATURE);
assert_eq!(
output.signed_transaction_data.to_hex(),
TRANSACTION_SIGNED_DATA
);
}
22 changes: 22 additions & 0 deletions rust/tw_tests/tests/chains/pactus/pactus_transaction_util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use tw_any_coin::test_utils::transaction_calc_tx_hash_utils::TransactionUtilHelper;
use tw_coin_registry::coin_type::CoinType;

use crate::chains::pactus::test_cases::transfer_1::{
TRANSACTION_NOT_SIGNED_DATA, TRANSACTION_SIGNED_DATA, TX_ID,
};

#[test]
fn test_pactus_transaction_util_calc_tx_hash_signed() {
let encoded_tx = TRANSACTION_SIGNED_DATA;
let tx_hash = TransactionUtilHelper::calc_tx_hash(CoinType::Pactus, encoded_tx);

assert_eq!(tx_hash, TX_ID);
}

#[test]
fn test_pactus_transaction_util_calc_tx_hash_not_signed() {
let encoded_tx = TRANSACTION_NOT_SIGNED_DATA;
let tx_hash = TransactionUtilHelper::calc_tx_hash(CoinType::Pactus, encoded_tx);

assert_eq!(tx_hash, TX_ID);
}
Loading

0 comments on commit b4fb941

Please sign in to comment.