def test_verify_confirmed_block(stubbed_blockhash): """Test verifying signature in a confirmed block.""" kp0, kp1, kp2, kp3 = (Keypair() for _ in range(4)) # Create a couple signed transaction txn1 = txlib.Transaction(recent_blockhash=stubbed_blockhash).add( transfer( TransferParams(from_pubkey=kp0.public_key, to_pubkey=kp1.public_key, lamports=123))) txn1.sign(kp0) txn2 = txlib.Transaction(recent_blockhash=stubbed_blockhash).add( transfer( TransferParams(from_pubkey=kp2.public_key, to_pubkey=kp3.public_key, lamports=456))) txn2.sign(kp2) # Build confirmed_block with dummy data for blockhases and balances confirmed_block = { "blockhash": stubbed_blockhash, "previousBlockhash": stubbed_blockhash, "transactions": [ { "transaction": txn1, "meta": { "fee": 0, "preBalances": [100000, 100000, 1, 1, 1], "postBalances": [99877, 100123, 1, 1, 1], "status": { "Ok": None }, "err": None, }, }, { "transaction": txn2, "meta": { "fee": 0, "preBalances": [100000, 100000, 1, 1, 1], "postBalances": [99544, 100456, 1, 1, 1], "status": { "Ok": None }, "err": None, }, }, ], "rewards": [], } # Verify signatures in confirmed_block assert all(tx_with_meta["transaction"].verify_signatures() for tx_with_meta in confirmed_block["transactions"]) # Test block with bogus signature bogus_signature = txlib.SigPubkeyPair(kp2.public_key, bytes([9] * 64)) # pylint: disable=protected-access txn1.signatures[0] = bogus_signature bad_confirmed_block = confirmed_block bad_confirmed_block["transactions"][0]["transaction"] = txn1 assert not all(tx_with_meta["transaction"].verify_signatures() for tx_with_meta in confirmed_block["transactions"])
def test_transfer_signatures(stubbed_blockhash): """Test signing transfer transactions.""" acc1, acc2 = Account(), Account() transfer1 = sp.transfer(sp.TransferParams(from_pubkey=acc1.public_key(), to_pubkey=acc2.public_key(), lamports=123)) transfer2 = sp.transfer(sp.TransferParams(from_pubkey=acc2.public_key(), to_pubkey=acc1.public_key(), lamports=123)) txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add(transfer1, transfer2) txn.sign(acc1, acc2) expected = txlib.Transaction(recent_blockhash=stubbed_blockhash, signatures=txn.signatures).add( transfer1, transfer2 ) assert txn == expected
def test_sign_partial(stubbed_blockhash): """Test paritally sigining a transaction.""" acc1, acc2 = Account(), Account() transfer = sp.transfer(sp.TransferParams(from_pubkey=acc1.public_key(), to_pubkey=acc2.public_key(), lamports=123)) partial_txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add(transfer) partial_txn.sign_partial(acc1, acc2.public_key()) assert len(partial_txn.signature()) == txlib.SIG_LENGTH assert len(partial_txn.signatures) == 2 assert not partial_txn.signatures[1].signature partial_txn.add_signer(acc2) expected_txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add(transfer) expected_txn.sign(acc1, acc2) assert partial_txn == expected_txn
def test_serialize_unsigned_transaction(stubbed_blockhash, stubbed_reciever, stubbed_sender): """Test to serialize an unsigned transaction.""" transfer = sp.transfer( sp.TransferParams(from_pubkey=stubbed_sender.public_key(), to_pubkey=stubbed_reciever, lamports=49) ) txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add(transfer) assert len(txn.signatures) == 0 # Empty signature array fails with pytest.raises(AttributeError): txn.serialize() assert len(txn.signatures) == 0 # Serialize message assert b64encode(txn.serialize_message()) == ( b"AQABAxOY9ixtGkV8UbpqS189vS9p/KkyFiGNyJl+QWvRfZPK/UOfzLZnJ/KJxcbeO8So/l3V13dwvI/xXD7u3LFK8/wAAAAAAAAA" b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMSa53YDeCBU8Xqd7OpDtETroO2xLG8dMcbg5KhL8FLrAQICAAEMAgAAADEAAAAAAAAA" ) assert len(txn.instructions) == 1 # Signature array populated with null signatures fails with pytest.raises(AttributeError): txn.serialize() assert len(txn.signatures) == 1 # Properly signed transaction succeeds txn.sign(stubbed_sender) assert len(txn.instructions) == 1 expected_serialization = b64decode( b"AVuErQHaXv0SG0/PchunfxHKt8wMRfMZzqV0tkC5qO6owYxWU2v871AoWywGoFQr4z+q/7mE8lIufNl/kxj+nQ0BAAEDE5j2" b"LG0aRXxRumpLXz29L2n8qTIWIY3ImX5Ba9F9k8r9Q5/Mtmcn8onFxt47xKj+XdXXd3C8j/FcPu7csUrz/AAAAAAAAAAAAAAA" b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAxJrndgN4IFTxep3s6kO0ROug7bEsbx0xxuDkqEvwUusBAgIAAQwCAAAAMQAAAAAAAAA=" ) assert txn.serialize() == expected_serialization assert len(txn.signatures) == 1
def test_dedup_signatures(stubbed_blockhash): """Test signature deduplication.""" acc1, acc2 = Account(), Account() transfer1 = sp.transfer(sp.TransferParams(from_pubkey=acc1.public_key(), to_pubkey=acc2.public_key(), lamports=123)) transfer2 = sp.transfer(sp.TransferParams(from_pubkey=acc1.public_key(), to_pubkey=acc2.public_key(), lamports=123)) txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add(transfer1, transfer2) txn.sign(acc1)
def test_transfer_signatures(stubbed_blockhash): """Test signing transfer transactions.""" kp1, kp2 = Keypair(), Keypair() transfer1 = sp.transfer( sp.TransferParams(from_pubkey=kp1.public_key, to_pubkey=kp2.public_key, lamports=123)) transfer2 = sp.transfer( sp.TransferParams(from_pubkey=kp2.public_key, to_pubkey=kp1.public_key, lamports=123)) txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add( transfer1, transfer2) txn.sign(kp1, kp2) expected = txlib.Transaction(recent_blockhash=stubbed_blockhash, signatures=txn.signatures).add( transfer1, transfer2) assert txn == expected
def test_sign_partial(stubbed_blockhash): """Test paritally sigining a transaction.""" kp1, kp2 = Keypair(), Keypair() transfer = sp.transfer( sp.TransferParams(from_pubkey=kp1.public_key, to_pubkey=kp2.public_key, lamports=123)) partial_txn = txlib.Transaction( recent_blockhash=stubbed_blockhash).add(transfer) partial_txn.sign_partial(kp1, kp2.public_key) assert len(partial_txn.signature()) == txlib.SIG_LENGTH assert len(partial_txn.signatures) == 2 assert not partial_txn.signatures[1].signature partial_txn.add_signer(kp2) expected_txn = txlib.Transaction( recent_blockhash=stubbed_blockhash).add(transfer) expected_txn.sign(kp1, kp2) assert partial_txn == expected_txn
def test_dedup_signatures(stubbed_blockhash): """Test signature deduplication.""" kp1, kp2 = Keypair(), Keypair() transfer1 = sp.transfer( sp.TransferParams(from_pubkey=kp1.public_key, to_pubkey=kp2.public_key, lamports=123)) transfer2 = sp.transfer( sp.TransferParams(from_pubkey=kp1.public_key, to_pubkey=kp2.public_key, lamports=123)) txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add( transfer1, transfer2) txn.sign(kp1)
def test_wire_format_and_desrialize(stubbed_blockhash, stubbed_reciever, stubbed_sender): """Test serialize/derialize transaction to/from wire format.""" transfer = sp.transfer( sp.TransferParams(from_pubkey=stubbed_sender.public_key(), to_pubkey=stubbed_reciever, lamports=49) ) expected_txn = txlib.Transaction(recent_blockhash=stubbed_blockhash).add(transfer) expected_txn.sign(stubbed_sender) wire_txn = b64decode( b"AVuErQHaXv0SG0/PchunfxHKt8wMRfMZzqV0tkC5qO6owYxWU2v871AoWywGoFQr4z+q/7mE8lIufNl/kxj+nQ0BAAEDE5j2" b"LG0aRXxRumpLXz29L2n8qTIWIY3ImX5Ba9F9k8r9Q5/Mtmcn8onFxt47xKj+XdXXd3C8j/FcPu7csUrz/AAAAAAAAAAAAAAA" b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAxJrndgN4IFTxep3s6kO0ROug7bEsbx0xxuDkqEvwUusBAgIAAQwCAAAAMQAAAAAAAAA=" ) txn = txlib.Transaction.deserialize(wire_txn) assert txn == expected_txn assert wire_txn == expected_txn.serialize()
def test_withdraw_from_vote_account(): withdrawer_keypair = Keypair.from_secret_key( bytes( [ 134, 123, 27, 208, 227, 175, 253, 99, 4, 81, 170, 231, 186, 141, 177, 142, 197, 139, 94, 6, 157, 2, 163, 89, 150, 121, 235, 86, 185, 22, 1, 233, 58, 133, 229, 39, 212, 71, 254, 72, 246, 45, 160, 156, 129, 199, 18, 189, 53, 143, 98, 72, 182, 106, 69, 29, 38, 145, 119, 190, 13, 105, 157, 112, ] ) ) vote_account_pubkey = PublicKey("CWqJy1JpmBcx7awpeANfrPk6AsQKkmego8ujjaYPGFEk") receiver_account_pubkey = PublicKey("A1V5gsis39WY42djdTKUFsgE5oamk4nrtg16WnKTuzZK") # solana withdraw-from-vote-account --dump-transaction-message \ # CWqJy1JpmBcx7awpeANfrPk6AsQKkmego8ujjaYPGFEk A1V5gsis39WY42djdTKUFsgE5oamk4nrtg16WnKTuzZK \ # --authorized-withdrawer withdrawer.json \ # 2 \ # --blockhash Add1tV7kJgNHhTtx3Dgs6dhC7kyXrGJQZ2tJGW15tLDH \ # --sign-only -k withdrawer.json wire_msg = base64.b64decode( b"AQABBDqF5SfUR/5I9i2gnIHHEr01j2JItmpFHSaRd74NaZ1wqxUGDtH5ah3TqEKWjcTmfHkpZC1h57NJL8Sx7Q6Olm2F2O70oOvzt1HgIVu+nySaSrWtJiK1eDacPPDWRxCwFgdhSB01dHS7fE12JOvTvbPYNV5z0RBD/A2jU4AAAAAAjxrQaMS7FjmaR++mvFr3XE6XbzMUTMJUIpITrUWBzGwBAwMBAgAMAwAAAACUNXcAAAAA" # noqa: E501 pylint: disable=line-too-long ) txn = txlib.Transaction(fee_payer=withdrawer_keypair.public_key) txn.recent_blockhash = "Add1tV7kJgNHhTtx3Dgs6dhC7kyXrGJQZ2tJGW15tLDH" txn.add( vp.withdraw_from_vote_account( vp.WithdrawFromVoteAccountParams( vote_account_from_pubkey=vote_account_pubkey, to_pubkey=receiver_account_pubkey, withdrawer=withdrawer_keypair.public_key, lamports=2_000_000_000, ) ) ) serialized_message = txn.serialize_message() assert serialized_message == wire_msg
def test_advance_nonce_and_transfer(): from_keypair = Keypair.from_secret_key( bytes([ 134, 123, 27, 208, 227, 175, 253, 99, 4, 81, 170, 231, 186, 141, 177, 142, 197, 139, 94, 6, 157, 2, 163, 89, 150, 121, 235, 86, 185, 22, 1, 233, 58, 133, 229, 39, 212, 71, 254, 72, 246, 45, 160, 156, 129, 199, 18, 189, 53, 143, 98, 72, 182, 106, 69, 29, 38, 145, 119, 190, 13, 105, 157, 112, ])) nonce_keypair = Keypair.from_secret_key( bytes([ 139, 81, 72, 75, 252, 57, 73, 247, 63, 130, 201, 76, 183, 43, 60, 197, 65, 154, 28, 240, 134, 0, 232, 108, 61, 123, 56, 26, 35, 201, 13, 39, 188, 128, 179, 175, 136, 5, 89, 185, 92, 183, 175, 131, 56, 53, 228, 11, 20, 34, 138, 148, 51, 27, 205, 76, 75, 148, 184, 34, 74, 129, 238, 225, ])) to_keypair = Keypair.from_secret_key( bytes([ 56, 246, 74, 56, 168, 158, 189, 97, 126, 149, 175, 70, 23, 14, 251, 206, 172, 69, 61, 247, 39, 226, 8, 68, 97, 159, 11, 196, 212, 57, 2, 1, 252, 124, 54, 3, 18, 109, 223, 27, 225, 28, 59, 202, 49, 248, 244, 17, 165, 33, 101, 59, 217, 79, 234, 217, 251, 85, 9, 6, 40, 0, 221, 10, ])) wire_txn = base64.b64decode( b"Abh4hJNaP/IUJlHGpQttaGNWkjOZx71uLEnVpT0SBaedmThsTogjsh87FW+EHeuJrsZii+tJbrq3oJ5UYXPzXwwBAAIFOoXl" b"J9RH/kj2LaCcgccSvTWPYki2akUdJpF3vg1pnXC8gLOviAVZuVy3r4M4NeQLFCKKlDMbzUxLlLgiSoHu4fx8NgMSbd8b4Rw7" b"yjH49BGlIWU72U/q2ftVCQYoAN0KBqfVFxksVo7gioRfc9KXiM8DXDFFshqzRNgGLqlAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" b"AAAAAAAAAAAAAAAAAE13Mu8zaQSpG0zzGHpG62nK56DbGhuS4kXMF/ChHY1jAgQDAQMABAQAAAAEAgACDAIAAACAhB4AAAAA" b"AA==") expected_txn = txlib.Transaction.deserialize(wire_txn) txn = txlib.Transaction(fee_payer=from_keypair.public_key) txn.recent_blockhash = "6DPp9aRRX6cLBqj5FepEvoccHFs3s8gUhd9t9ftTwAta" txn.add( sp.nonce_advance( sp.AdvanceNonceParams( nonce_pubkey=nonce_keypair.public_key, authorized_pubkey=from_keypair.public_key, ))) txn.add( sp.transfer( sp.TransferParams(from_pubkey=from_keypair.public_key, to_pubkey=to_keypair.public_key, lamports=2000000))) txn_hash = txn.serialize_message() txn.add_signature(from_keypair.public_key, from_keypair.sign(txn_hash).signature) assert txn == expected_txn