| 390 | } |
| 391 | |
| 392 | BOOST_AUTO_TEST_CASE(btck_transaction_tests) |
| 393 | { |
| 394 | auto tx_data{hex_string_to_byte_vec("02000000013f7cebd65c27431a90bba7f796914fe8cc2ddfc3f2cbd6f7e5f2fc854534da95000000006b483045022100de1ac3bcdfb0332207c4a91f3832bd2c2915840165f876ab47c5f8996b971c3602201c6c053d750fadde599e6f5c4e1963df0f01fc0d97815e8157e3d59fe09ca30d012103699b464d1d8bc9e47d4fb1cdaa89a1c5783d68363c4dbc4b524ed3d857148617feffffff02836d3c01000000001976a914fc25d6d5c94003bf5b0c7b640a248e2c637fcfb088ac7ada8202000000001976a914fbed3d9b11183209a57999d54d59f67c019e756c88ac6acb0700")}; |
| 395 | auto tx{Transaction{tx_data}}; |
| 396 | auto tx_data_2{hex_string_to_byte_vec("02000000000101904f4ee5c87d20090b642f116e458cd6693292ad9ece23e72f15fb6c05b956210500000000fdffffff02e2010000000000002251200839a723933b56560487ec4d67dda58f09bae518ffa7e148313c5696ac837d9f10060000000000002251205826bcdae7abfb1c468204170eab00d887b61ab143464a4a09e1450bdc59a3340140f26e7af574e647355830772946356c27e7bbc773c5293688890f58983499581be84de40be7311a14e6d6422605df086620e75adae84ff06b75ce5894de5e994a00000000")}; |
| 397 | auto tx2{Transaction{tx_data_2}}; |
| 398 | CheckHandle(tx, tx2); |
| 399 | |
| 400 | auto invalid_data = hex_string_to_byte_vec("012300"); |
| 401 | BOOST_CHECK_THROW(Transaction{invalid_data}, std::runtime_error); |
| 402 | auto empty_data = hex_string_to_byte_vec(""); |
| 403 | BOOST_CHECK_THROW(Transaction{empty_data}, std::runtime_error); |
| 404 | |
| 405 | BOOST_CHECK_EQUAL(tx.CountOutputs(), 2); |
| 406 | BOOST_CHECK_EQUAL(tx.CountInputs(), 1); |
| 407 | BOOST_CHECK_EQUAL(tx.GetLocktime(), 510826); |
| 408 | auto broken_tx_data{std::span<std::byte>{tx_data.begin(), tx_data.begin() + 10}}; |
| 409 | BOOST_CHECK_THROW(Transaction{broken_tx_data}, std::runtime_error); |
| 410 | auto input{tx.GetInput(0)}; |
| 411 | BOOST_CHECK_EQUAL(input.GetSequence(), 0xfffffffe); |
| 412 | auto output{tx.GetOutput(tx.CountOutputs() - 1)}; |
| 413 | BOOST_CHECK_EQUAL(output.Amount(), 42130042); |
| 414 | auto script_pubkey{output.GetScriptPubkey()}; |
| 415 | { |
| 416 | auto tx_new{Transaction{tx_data}}; |
| 417 | // This is safe, because we now use copy assignment |
| 418 | TransactionOutput output = tx_new.GetOutput(tx_new.CountOutputs() - 1); |
| 419 | ScriptPubkey script = output.GetScriptPubkey(); |
| 420 | |
| 421 | TransactionOutputView output2 = tx_new.GetOutput(tx_new.CountOutputs() - 1); |
| 422 | BOOST_CHECK_NE(output.get(), output2.get()); |
| 423 | BOOST_CHECK_EQUAL(output.Amount(), output2.Amount()); |
| 424 | TransactionOutput output3 = output2; |
| 425 | BOOST_CHECK_NE(output3.get(), output2.get()); |
| 426 | BOOST_CHECK_EQUAL(output3.Amount(), output2.Amount()); |
| 427 | |
| 428 | // Non-owned view |
| 429 | ScriptPubkeyView script2 = output.GetScriptPubkey(); |
| 430 | BOOST_CHECK_NE(script.get(), script2.get()); |
| 431 | check_equal(script.ToBytes(), script2.ToBytes()); |
| 432 | |
| 433 | // Non-owned to owned |
| 434 | ScriptPubkey script3 = script2; |
| 435 | BOOST_CHECK_NE(script3.get(), script2.get()); |
| 436 | check_equal(script3.ToBytes(), script2.ToBytes()); |
| 437 | } |
| 438 | BOOST_CHECK_EQUAL(output.Amount(), 42130042); |
| 439 | |
| 440 | auto tx_roundtrip{Transaction{tx.ToBytes()}}; |
| 441 | check_equal(tx_roundtrip.ToBytes(), tx_data); |
| 442 | |
| 443 | // The following code is unsafe, but left here to show limitations of the |
| 444 | // API, because we preserve the output view beyond the lifetime of the |
| 445 | // transaction. The view type wrapper should make this clear to the user. |
| 446 | // auto get_output = [&]() -> TransactionOutputView { |
| 447 | // auto tx{Transaction{tx_data}}; |
| 448 | // return tx.GetOutput(0); |
| 449 | // }; |
nothing calls this directly
no test coverage detected