Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] implement p2pkh #197

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ mod tests {
mod test_coinbase;
mod test_transactions;
mod test_p2pk;
mod test_p2pkh;
}
mod main;
1 change: 1 addition & 0 deletions src/opcodes/tests/test_crypto.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::errors::Error;
use crate::scriptnum::ScriptNum;
use crate::scriptflags::ScriptFlags;

#[test]
fn test_opcode_sha256_1() {
let program = "OP_1 OP_SHA256";
let mut engine = utils::test_compile_and_run(program);
Expand Down
94 changes: 94 additions & 0 deletions src/tests/test_p2pkh.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use crate::transaction::TransactionTrait;
use crate::utxo::UTXO;
use crate::validate;
use crate::utils::hex_to_bytecode;

#[test]
fn test_p2pkh_transaction() {
// First ever P2PKH transaction
// tx: 6f7cf9580f1c2dfb3c4d5d043cdbb128c640e3f20161245aa7372e9666168516
let raw_transaction_hex =
"0x0100000002f60b5e96f09422354ab150b0e506c4bffedaf20216d30059cc5a3061b4c83dff000000004a493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01fffffffff7272ef43189f5553c2baea50f59cde99b3220fd518884d932016d055895b62d000000004a493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01ffffffff0100e40b54020000001976a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac00000000";
let raw_transaction = hex_to_bytecode(@raw_transaction_hex);
let transaction = TransactionTrait::deserialize(raw_transaction);

let prevout_pk_script_1 =
"0x4104c9560dc538db21476083a5c65a34c7cc219960b1e6f27a87571cd91edfd00dac16dca4b4a7c4ab536f85bc263b3035b762c5576dc6772492b8fb54af23abff6dac";
let prevout_1 = UTXO {
amount: 5000000000, pubkey_script: hex_to_bytecode(@prevout_pk_script_1), block_height: 509
};
let prevout_pk_script_2 =
"0x41043987a76015929873f06823f4e8d93abaaf7bcf55c6a564bed5b7f6e728e6c4cb4e2c420fe14d976f7e641d8b791c652dfeee9da584305ae544eafa4f7be6f777ac";
let prevout_2 = UTXO {
amount: 50000000000, pubkey_script: hex_to_bytecode(@prevout_pk_script_2), block_height: 357
};
let utxo_hints = array![prevout_1, prevout_2];

let res = validate::validate_transaction(transaction, 0, utxo_hints);
assert!(res.is_ok(), "Transaction validation failed");
}

#[test]
fn test_p2pkh_transaction_spend() {
// Spend the first ever P2PKH transaction output
// tx: 12e753ef5cc30925a6eee2c457aa7f53022443ca013ea81882a6b59b69e342a6
let raw_transaction_hex =
"0x01000000030dd7891efbf67da47c651531db8aab3144ed7a524e4ae1e30b773525e27ddd7b000000004948304502206f6a68710a51f77e5a1fa4d1037a23a76723724a51fd54710949e0189ee02dfa022100dad3454ade12fe84f3818e14c41ec2e02bbb154dd3136a094cdf86f67ebbe0b601ffffffff16851666962e37a75a246101f2e340c628b1db3c045d4d3cfb2d1c0f58f97c6f000000008b48304502203f004eeed0cef2715643e2f25a27a28f3c578e94c7f0f6a4df104e7d163f7f8f022100b8b248c1cfd8f77a0365107a9511d759b7544d979dd152a955c867afac0ef7860141044d05240cfbd8a2786eda9dadd520c1609b8593ff8641018d57703d02ba687cf2f187f0cee2221c3afb1b5ff7888caced2423916b61444666ca1216f26181398cffffffffffda5d38e91fd9a0d92872d51f83cb746fc7bf5d3ff13402f8d0d5ed60ddc79c0000000049483045022100b6fd43f2fa16e092678283f64d2e08fb2070b4af2b3ddfb9ca3c5e238288acaa02200c5a28e0a4fc1a540f6eeb30ccc4788050eae46964fe33ccb4500c3de1320c2501ffffffff02c0c62d00000000001976a91417194e1bd175fb5b1b2a1f9d221f6f5c29e1928388ac00c817a8040000001976a91465bda9b05f7e9a8f96a7f4ba0996a877708ef90888ac00000000";
let raw_transaction = hex_to_bytecode(@raw_transaction_hex);
let transaction = TransactionTrait::deserialize(raw_transaction);

let prevout_pk_script_0 =
"0x4104889fcdfd7c5430d13f1eb5f508e2e87f38d2406fad8425a824e032ccb371ef62465331e1a6334d7c3770a2ad2a958e740130343399d01dbd87426db850f9faf9ac";
let prevout_pkh_script_1 = "0x76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac";
let prevout_pk_script_2 =
"0x4104f51707ee3fd26b490bb83582f22c73b97c364b9c51a80c49e6a9bc491538f5206fc0ca8fc4c97dfd0a8b2ae9b82d1ef94599ce51eaf9ba82ce4a69d9ac9dc225ac";

let prev_out0 = UTXO {
amount: 5003000000,
pubkey_script: hex_to_bytecode(@prevout_pk_script_0),
block_height: 12983
};

let prev_out1 = UTXO {
amount: 10000000000,
pubkey_script: hex_to_bytecode(@prevout_pkh_script_1),
block_height: 728
};

let prev_out2 = UTXO {
amount: 5000000000,
pubkey_script: hex_to_bytecode(@prevout_pk_script_2),
block_height: 17233
};

let utxo_hints = array![prev_out0, prev_out1, prev_out2];

// Run Shinigami and validate the transaction execution
let res = validate::validate_transaction(transaction, 0, utxo_hints);
assert!(res.is_ok(), "Transaction validation failed");
}

#[ignore]
#[test]
fn test_10000_btc_pizza_transaction() { // The famous 10000 BTC pizza transaction
// tx: a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d
// TODO
}

#[test]
fn test_block_770000_p2pkh_transaction() {
// tx: a2bf21f6d8b7aa77c740d0374e4759791d97c0134bc918c93bae8e14879c8ecc
let raw_transaction_hex =
"0x0200000001c3cbbd0f9ac1f59225df1381c10c4b104ed7d78beef73e89cbd163c8d98b729e000000006a47304402202acb8afaa5745d1fd99dab6e74d89ee679daca1973796f61916e6e27905cd01b022067120362c1145cdd2a2de182435618b3c356a72849718997e5546d62ea9925fb012102e34755efb7b73a51f0a2facc10c9aab73b99a3f676c60fe5a7e865c75d61cce3feffffff02acf15608020000001976a9149ee1cd0c085b88bd7b22e44abe52734e0a61c94288ac404b4c00000000001976a914a7e9478b4f77c490c32472cfe8ad672d24fc77a888accfbf0b00";
let raw_transaction = hex_to_bytecode(@raw_transaction_hex);
let transaction = TransactionTrait::deserialize(raw_transaction);

let prevout_pk_script = "0x76a9140900bb14c7cb6a52fd8a22fd68a5986eb193c9f588ac";
let prevout = UTXO {
amount: 8734850959, pubkey_script: hex_to_bytecode(@prevout_pk_script), block_height: 769998
};
let utxo_hints = array![prevout];

let res = validate::validate_transaction(transaction, 0, utxo_hints);
assert!(res.is_ok(), "Transaction validation failed");
}
57 changes: 56 additions & 1 deletion src/tests/test_transactions.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,61 @@ fn test_deserialize_transaction() {
assert_eq!(transaction.locktime, 0, "Lock time is not correct");
}


#[test]
fn test_deserialize_first_p2pkh_transaction() {
// First ever P2PKH transaction
// tx: 6f7cf9580f1c2dfb3c4d5d043cdbb128c640e3f20161245aa7372e9666168516
let raw_transaction_hex =
"0x0100000002f60b5e96f09422354ab150b0e506c4bffedaf20216d30059cc5a3061b4c83dff000000004a493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01fffffffff7272ef43189f5553c2baea50f59cde99b3220fd518884d932016d055895b62d000000004a493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01ffffffff0100e40b54020000001976a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac00000000";
let raw_transaction = utils::hex_to_bytecode(@raw_transaction_hex);
let transaction = TransactionTrait::deserialize(raw_transaction);

assert_eq!(transaction.version, 1, "Version is not correct");
assert_eq!(transaction.transaction_inputs.len(), 2, "Transaction inputs length is not correct");
let input0 = transaction.transaction_inputs[0];
let expected_txid_hex = "0xf60b5e96f09422354ab150b0e506c4bffedaf20216d30059cc5a3061b4c83dff";
let expected_txid = utils::hex_to_bytecode(@expected_txid_hex);
let expected_sig_script_hex =
"0x493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01";
let expected_sig_script = utils::hex_to_bytecode(@expected_sig_script_hex);
assert_eq!(
input0.previous_outpoint.txid,
@utils::u256_from_byte_array_with_offset(@expected_txid, 0, 32),
"Outpoint txid on input 1 is not correct"
);
assert_eq!(input0.previous_outpoint.vout, @0, "Outpoint vout on input 1 is not correct");
assert_eq!(
input0.signature_script, @expected_sig_script, "Script sig on input 1 is not correct"
);
assert_eq!(input0.sequence, @0xFFFFFFFF, "Sequence on input 1 is not correct");

let input1 = transaction.transaction_inputs[1];
let expected_txid_hex = "0xf7272ef43189f5553c2baea50f59cde99b3220fd518884d932016d055895b62d";
let expected_txid = utils::hex_to_bytecode(@expected_txid_hex);
let expected_sig_script_hex =
"0x493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01";
let expected_sig_script = utils::hex_to_bytecode(@expected_sig_script_hex);
assert_eq!(
input1.previous_outpoint.txid,
@utils::u256_from_byte_array_with_offset(@expected_txid, 0, 32),
"Outpoint txid on input 2 is not correct"
);
assert_eq!(input1.previous_outpoint.vout, @0, "Outpoint vout on input 2 is not correct");
assert_eq!(
input1.signature_script, @expected_sig_script, "Script sig on input 2 is not correct"
);
assert_eq!(input1.sequence, @0xFFFFFFFF, "Sequence on input 2 is not correct");

let output0 = transaction.transaction_outputs[0];
assert_eq!(output0.value, @10000000000, "Output 1 value is not correct");
let expected_pk_script_hex = "0x76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac";
let expected_pk_script = utils::hex_to_bytecode(@expected_pk_script_hex);
assert_eq!(output0.publickey_script, @expected_pk_script, "Output 1 pk_script is not correct");

assert_eq!(transaction.locktime, 0, "Lock time is not correct");
}

#[test]
fn test_deserialize_coinbase_transaction() { // TODO
}
Expand All @@ -78,7 +133,7 @@ fn test_validate_transaction() {
let raw_transaction = utils::hex_to_bytecode(@raw_transaction_hex);
let transaction = TransactionTrait::deserialize(raw_transaction);

// Setup UTXO hints ( previous valid ouputs used to execute this transaction )
// Setup UTXO hints ( previous valid outputs used to execute this transaction )
let prevout_pk_script =
"0x410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac";
let prev_out = UTXO {
Expand Down