From 0553f7e2e7c2e64e8dd33a7cb6c44bee0e3d4a9c Mon Sep 17 00:00:00 2001 From: Ori Newman Date: Wed, 9 Jan 2019 17:55:25 +0200 Subject: [PATCH 1/2] [DEV-342] change subnetworkid to hash160 (#154) * [DEV-342] Make subnetworkid Hash160 * [DEV-342] Fix tests * [DEV-342] Fix rpcserver.go mismatched types * [DEV-342] Change subnetworkhash type and package to subnetworkid * [DEV-342] Add subnetworkid package --- blockdag/accept_test.go | 5 +- blockdag/dag_test.go | 4 +- blockdag/example_test.go | 2 +- blockdag/indexers/txindex_test.go | 186 ++++++++++++++-------------- blockdag/subnetworks.go | 14 +-- blockdag/testdata/blk_0_to_4.dat | Bin 1721 -> 1817 bytes blockdag/testdata/blk_3A.dat | Bin 410 -> 435 bytes blockdag/testdata/blk_3B.dat | Bin 203 -> 215 bytes blockdag/testdata/blk_3C.dat | Bin 235 -> 247 bytes blockdag/testdata/blk_3D.dat | Bin 456 -> 480 bytes blockdag/validate.go | 3 +- blockdag/validate_test.go | 13 +- config/config.go | 17 +-- config/config_test.go | 12 +- dagconfig/genesis.go | 56 ++++----- dagconfig/genesis_test.go | 72 ++++++----- database/example_test.go | 2 +- database/testdata/blocks1-256.bz2 | Bin 9966 -> 9945 bytes mining/mining.go | 5 +- mining/policy_test.go | 8 +- server/rpc/rpcserver.go | 10 +- util/block_test.go | 16 +-- util/bloom/filter_test.go | 58 +++++---- util/bloom/merkleblock_test.go | 35 +++--- util/coinset/coins_test.go | 4 +- util/subnetworkid/subnetworkid.go | 198 ++++++++++++++++++++++++++++++ util/tx_test.go | 2 +- util/txsort/testdata/bip69-1.hex | 2 +- util/txsort/testdata/bip69-2.hex | 2 +- util/txsort/testdata/bip69-3.hex | 2 +- util/txsort/testdata/bip69-4.hex | 2 +- util/txsort/testdata/bip69-5.hex | 2 +- util/txsort/txsort_test.go | 20 +-- wire/message_test.go | 4 +- wire/msgblock_test.go | 8 +- wire/msgtx.go | 36 +++--- wire/msgtx_test.go | 46 ++++--- 37 files changed, 546 insertions(+), 300 deletions(-) create mode 100644 util/subnetworkid/subnetworkid.go diff --git a/blockdag/accept_test.go b/blockdag/accept_test.go index 1b8e995d7..3836909be 100644 --- a/blockdag/accept_test.go +++ b/blockdag/accept_test.go @@ -56,10 +56,13 @@ func TestMaybeAcceptBlockErrors(t *testing.T) { // Add a valid block and mark it as invalid block1 := blocks[1] - _, err = dag.ProcessBlock(block1, BFNone) + isOrphan, err := dag.ProcessBlock(block1, BFNone) if err != nil { t.Fatalf("TestMaybeAcceptBlockErrors: Valid block unexpectedly returned an error: %s", err) } + if isOrphan { + t.Fatalf("TestMaybeAcceptBlockErrors: incorrectly returned block 1 is an orphan") + } blockNode1 := dag.index.LookupNode(block1.Hash()) dag.index.SetStatusFlags(blockNode1, statusValidateFailed) diff --git a/blockdag/dag_test.go b/blockdag/dag_test.go index 8f64a5b4c..08ff87d42 100644 --- a/blockdag/dag_test.go +++ b/blockdag/dag_test.go @@ -185,10 +185,10 @@ func TestHaveBlock(t *testing.T) { {hash: dagconfig.SimNetParams.GenesisHash.String(), want: true}, // Block 3b should be present (as a second child of Block 2). - {hash: "74e325a48f84020f3d36c07edf9cda95d93cff866ff8e8df5d2825d2ced6d28f", want: true}, + {hash: "2664223a8b2abba475ed5760433e8204806c17b60f12d826b876cccbf5f74be6", want: true}, // Block 100000 should be present (as an orphan). - {hash: "566ca0e828951be69df4b45b82b4eb9b593b712a0018a382cb75790f85810be3", want: true}, + {hash: "66965d8ebcdccae2b3791f652326ef1063fa0a7e506c66f68e0c7bbb59104711", want: true}, // Random hashes should not be available. {hash: "123", want: false}, diff --git a/blockdag/example_test.go b/blockdag/example_test.go index 99708e324..4a2459b76 100644 --- a/blockdag/example_test.go +++ b/blockdag/example_test.go @@ -68,7 +68,7 @@ func ExampleBlockDAG_ProcessBlock() { fmt.Printf("Block accepted. Is it an orphan?: %v", isOrphan) // Output: - // Failed to process block: already have block 47c205482e0a2aa1f5503ec73ea0ffe5226f9d9357f037dcde79f75d85171634 + // Failed to process block: already have block 4acd12ea38e16dd28b067c13f677511ac0a4d9074c932223082fd444655fd9ca } // This example demonstrates how to convert the compact "bits" in a block header diff --git a/blockdag/indexers/txindex_test.go b/blockdag/indexers/txindex_test.go index 3d7c767d0..f27916e1d 100644 --- a/blockdag/indexers/txindex_test.go +++ b/blockdag/indexers/txindex_test.go @@ -107,21 +107,21 @@ var block1 = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{ [32]byte{ // Make go vet happy. - 0x34, 0x16, 0x17, 0x85, 0x5d, 0xf7, 0x79, 0xde, - 0xdc, 0x37, 0xf0, 0x57, 0x93, 0x9d, 0x6f, 0x22, - 0xe5, 0xff, 0xa0, 0x3e, 0xc7, 0x3e, 0x50, 0xf5, - 0xa1, 0x2a, 0x0a, 0x2e, 0x48, 0x05, 0xc2, 0x47, + 0xca, 0xd9, 0x5f, 0x65, 0x44, 0xd4, 0x2f, 0x08, + 0x23, 0x22, 0x93, 0x4c, 0x07, 0xd9, 0xa4, 0xc0, + 0x1a, 0x51, 0x77, 0xf6, 0x13, 0x7c, 0x06, 0x8b, + 0xd2, 0x6d, 0xe1, 0x38, 0xea, 0x12, 0xcd, 0x4a, }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. - 0x6c, 0x56, 0xa7, 0x7d, 0xfa, 0x18, 0x89, 0xdc, - 0x20, 0x60, 0x3f, 0x51, 0x32, 0xa8, 0xdc, 0x47, - 0x5f, 0x43, 0xb7, 0xe8, 0xae, 0x24, 0x22, 0x34, - 0x64, 0x91, 0xe7, 0xd5, 0xac, 0xc0, 0xed, 0x88, + 0x80, 0x57, 0x44, 0xf9, 0xee, 0xb7, 0x14, 0x05, + 0x8c, 0x37, 0x2e, 0x41, 0x82, 0x98, 0xcd, 0x0d, + 0xc8, 0xd1, 0xd1, 0x11, 0x9b, 0xe2, 0xc1, 0x4e, + 0x4b, 0x7c, 0x02, 0xd1, 0x11, 0xe0, 0x50, 0x11, }), - Timestamp: time.Unix(0x5c238b71, 0), + Timestamp: time.Unix(0x5c34c291, 0), Bits: 0x207fffff, - Nonce: 0x00000000, + Nonce: 0xdffffffffffffff9, }, Transactions: []*wire.MsgTx{ { @@ -161,21 +161,21 @@ var block2 = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{ [32]byte{ // Make go vet happy. - 0x69, 0xe9, 0xd1, 0xa2, 0xd0, 0x5f, 0x35, 0x39, - 0x6b, 0xa7, 0x1d, 0xeb, 0x97, 0x33, 0x7f, 0xcf, - 0xa1, 0xa8, 0xc5, 0x1f, 0x31, 0x82, 0x09, 0x62, - 0x79, 0xb3, 0xf9, 0xd6, 0x66, 0x3f, 0xd7, 0x45, + 0xf1, 0x15, 0xa7, 0xd8, 0x0e, 0xb6, 0x88, 0x25, + 0x1a, 0x9b, 0xc8, 0x6f, 0x1f, 0x71, 0x79, 0xc9, + 0x33, 0xca, 0xd7, 0x79, 0xe5, 0x40, 0x98, 0xd6, + 0x1b, 0x0b, 0x59, 0x3b, 0x98, 0x35, 0x7a, 0x1f, }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. - 0x29, 0xdc, 0xa7, 0x2b, 0x14, 0xfb, 0x5b, 0xe4, - 0x3c, 0x7c, 0x91, 0x3c, 0x54, 0x7c, 0xbe, 0x20, - 0x98, 0xe8, 0xc6, 0x01, 0x65, 0x59, 0x02, 0xa5, - 0xa2, 0xf5, 0xf1, 0x9f, 0x3b, 0x3f, 0x28, 0x3c, + 0x22, 0x71, 0xda, 0xba, 0x9d, 0x3c, 0xc8, 0xea, + 0xc7, 0x54, 0x26, 0x11, 0x31, 0x1c, 0x1a, 0x09, + 0x70, 0xde, 0x53, 0x6d, 0xaa, 0x32, 0xa6, 0x00, + 0x7a, 0x6b, 0xc4, 0x61, 0x3b, 0xc7, 0x1e, 0x13, }), - Timestamp: time.Unix(0x5c238b72, 0), + Timestamp: time.Unix(0x5c34c292, 0), Bits: 0x207fffff, - Nonce: 0x2000000000000001, + Nonce: 0xdffffffffffffffc, }, Transactions: []*wire.MsgTx{ { @@ -213,28 +213,28 @@ var block2 = wire.MsgBlock{ { PreviousOutPoint: wire.OutPoint{ Hash: daghash.Hash{ - 0x6c, 0x56, 0xa7, 0x7d, 0xfa, 0x18, 0x89, 0xdc, - 0x20, 0x60, 0x3f, 0x51, 0x32, 0xa8, 0xdc, 0x47, - 0x5f, 0x43, 0xb7, 0xe8, 0xae, 0x24, 0x22, 0x34, - 0x64, 0x91, 0xe7, 0xd5, 0xac, 0xc0, 0xed, 0x88, + 0x80, 0x57, 0x44, 0xf9, 0xee, 0xb7, 0x14, 0x05, + 0x8c, 0x37, 0x2e, 0x41, 0x82, 0x98, 0xcd, 0x0d, + 0xc8, 0xd1, 0xd1, 0x11, 0x9b, 0xe2, 0xc1, 0x4e, + 0x4b, 0x7c, 0x02, 0xd1, 0x11, 0xe0, 0x50, 0x11, }, Index: 0, }, SignatureScript: []byte{ - 0x46, 0x30, 0x43, 0x02, 0x1f, 0x56, 0x0a, 0xfa, - 0x84, 0xc7, 0x80, 0xe1, 0x56, 0xe0, 0xec, 0x18, - 0xe7, 0xd7, 0x02, 0x87, 0x1f, 0x22, 0x62, 0xda, - 0xfa, 0x33, 0x82, 0xfc, 0x1d, 0x01, 0x7a, 0x0e, - 0xa5, 0x5f, 0x4e, 0xce, 0x02, 0x20, 0x6d, 0x1f, - 0xaf, 0xca, 0x91, 0x33, 0x8d, 0xfb, 0xb7, 0xa2, - 0x40, 0xf9, 0x4f, 0x3c, 0x04, 0xc9, 0x47, 0x29, - 0x6a, 0x7f, 0x45, 0x62, 0x0a, 0x2a, 0x7d, 0x93, - 0x7b, 0xe2, 0xc9, 0xba, 0x15, 0xb3, 0x01, 0x21, - 0x02, 0xa6, 0x73, 0x63, 0x8c, 0xb9, 0x58, 0x7c, - 0xb6, 0x8e, 0xa0, 0x8d, 0xbe, 0xf6, 0x85, 0xc6, - 0xf2, 0xd2, 0xa7, 0x51, 0xa8, 0xb3, 0xc6, 0xf2, - 0xa7, 0xe9, 0xa4, 0x99, 0x9e, 0x6e, 0x4b, 0xfa, - 0xf5, + 0x47, 0x30, 0x44, 0x02, 0x20, 0x08, 0x3e, 0x75, + 0x3e, 0x0a, 0xbc, 0x0b, 0x39, 0x06, 0xf2, 0x2c, + 0x99, 0x85, 0xf2, 0xde, 0xa7, 0x83, 0x3e, 0x6b, + 0x5a, 0x69, 0x37, 0x51, 0x4c, 0xf8, 0x40, 0x59, + 0x4c, 0x2f, 0x50, 0x1c, 0x04, 0x02, 0x20, 0x06, + 0x21, 0xd9, 0xde, 0x0c, 0x10, 0xca, 0x9d, 0xa4, + 0x5f, 0xe0, 0xfe, 0x3b, 0x33, 0x1d, 0x92, 0x6e, + 0xc4, 0x02, 0xe4, 0x3c, 0xd4, 0x3c, 0xea, 0xf8, + 0xd8, 0xe5, 0x14, 0x3f, 0x56, 0xe9, 0x5b, 0x01, + 0x21, 0x02, 0xa6, 0x73, 0x63, 0x8c, 0xb9, 0x58, + 0x7c, 0xb6, 0x8e, 0xa0, 0x8d, 0xbe, 0xf6, 0x85, + 0xc6, 0xf2, 0xd2, 0xa7, 0x51, 0xa8, 0xb3, 0xc6, + 0xf2, 0xa7, 0xe9, 0xa4, 0x99, 0x9e, 0x6e, 0x4b, + 0xfa, 0xf5, }, Sequence: math.MaxUint64, }, @@ -262,23 +262,23 @@ var block3Tx = &wire.MsgTx{ { PreviousOutPoint: wire.OutPoint{ Hash: daghash.Hash{ - 0x99, 0x30, 0x0c, 0x6e, 0xad, 0x5c, 0x9c, 0xcf, - 0xfc, 0xcb, 0x62, 0xfd, 0x39, 0xe3, 0xc1, 0x7e, - 0x87, 0x17, 0xec, 0x9e, 0x7b, 0xc7, 0x81, 0xe0, - 0x8f, 0x15, 0x85, 0xcb, 0x6d, 0x54, 0x74, 0x3e, + 0x65, 0x63, 0x9f, 0x61, 0x7c, 0xaa, 0xc1, 0x4a, + 0x96, 0x7d, 0x8a, 0xc0, 0x4b, 0x97, 0xc5, 0xf3, + 0x86, 0xbe, 0x54, 0x03, 0x26, 0x00, 0x0c, 0xc5, + 0xd8, 0xbb, 0x75, 0x96, 0x1b, 0xdb, 0xa7, 0x5b, }, Index: 0, }, SignatureScript: []byte{ - 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0x91, 0xa3, - 0xb4, 0x99, 0x57, 0xb2, 0x53, 0x2f, 0x7f, 0xaf, - 0xb6, 0x4d, 0x9d, 0x7b, 0x1b, 0xa2, 0x41, 0x03, - 0x1a, 0xe5, 0xfd, 0x4d, 0xe1, 0x5a, 0x7e, 0x9f, - 0xe3, 0xdd, 0x44, 0xb8, 0x62, 0x13, 0x02, 0x20, - 0x7a, 0xba, 0x9a, 0xe6, 0xa5, 0x81, 0x43, 0xb9, - 0x05, 0x66, 0xc1, 0xa3, 0x79, 0xad, 0xf0, 0xf4, - 0xb9, 0xfe, 0x28, 0x13, 0x35, 0xd6, 0x84, 0x95, - 0x08, 0xd0, 0xaa, 0x1d, 0xb7, 0x5b, 0x88, 0x4c, + 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0x94, 0x6a, + 0x03, 0xb4, 0xab, 0xc3, 0xce, 0x5f, 0xc9, 0x85, + 0xbd, 0xb1, 0xdf, 0x94, 0x26, 0xd0, 0x27, 0x20, + 0x63, 0xdd, 0xd6, 0xd6, 0xce, 0x29, 0xb5, 0xae, + 0x91, 0x50, 0x57, 0x18, 0xc3, 0x26, 0x02, 0x20, + 0x56, 0x99, 0xa2, 0x8a, 0xbb, 0x2f, 0xfe, 0x09, + 0x11, 0x54, 0x42, 0xa7, 0xb3, 0x52, 0x35, 0xf8, + 0xa4, 0x3e, 0x01, 0x61, 0xfa, 0xb9, 0x09, 0x6d, + 0x48, 0x38, 0xa7, 0xc1, 0xfd, 0x6f, 0x9e, 0x5b, 0x01, 0x21, 0x02, 0xa6, 0x73, 0x63, 0x8c, 0xb9, 0x58, 0x7c, 0xb6, 0x8e, 0xa0, 0x8d, 0xbe, 0xf6, 0x85, 0xc6, 0xf2, 0xd2, 0xa7, 0x51, 0xa8, 0xb3, @@ -308,19 +308,19 @@ var block3 = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{ [32]byte{ // Make go vet happy. - 0x96, 0x2d, 0x1d, 0x2b, 0xc2, 0xf9, 0x30, 0x43, - 0x88, 0x23, 0xdb, 0x75, 0x73, 0x43, 0xb8, 0xb6, - 0x76, 0x34, 0x42, 0x55, 0x8f, 0x44, 0x2a, 0x6f, - 0xb1, 0xac, 0x7e, 0x9b, 0x1f, 0x9f, 0x00, 0x19, + 0x41, 0x27, 0x85, 0x25, 0x0e, 0x8e, 0xdb, 0xf3, + 0xb5, 0xdd, 0xfa, 0xb9, 0x75, 0xc0, 0x4f, 0xe8, + 0x88, 0xff, 0x04, 0x08, 0xe9, 0x0a, 0x93, 0x8f, + 0x45, 0x04, 0x03, 0x73, 0xc6, 0x24, 0x08, 0x72, }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. - 0x58, 0xbd, 0x06, 0x58, 0x0a, 0xab, 0x32, 0x10, - 0x97, 0x5c, 0xc6, 0x97, 0xb0, 0xde, 0xb9, 0xe2, - 0xa6, 0x21, 0x67, 0xe5, 0x2f, 0xa3, 0xc5, 0xb2, - 0xba, 0x8f, 0xd3, 0xc7, 0x4c, 0x18, 0x87, 0xc5, + 0x93, 0x9b, 0x93, 0x78, 0x9f, 0xca, 0x8c, 0xab, + 0x73, 0x04, 0x64, 0x01, 0xc9, 0x4f, 0x67, 0xf4, + 0xb7, 0x6f, 0x0f, 0xd4, 0x0a, 0xe9, 0x77, 0x81, + 0xa7, 0x18, 0xf8, 0x60, 0xe8, 0x20, 0x45, 0xf2, }), - Timestamp: time.Unix(0x5c238b73, 0), + Timestamp: time.Unix(0x5c34c293, 0), Bits: 0x207fffff, Nonce: 0xdffffffffffffff9, }, @@ -363,21 +363,21 @@ var block3A = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{ [32]byte{ // Make go vet happy. - 0x96, 0x2d, 0x1d, 0x2b, 0xc2, 0xf9, 0x30, 0x43, - 0x88, 0x23, 0xdb, 0x75, 0x73, 0x43, 0xb8, 0xb6, - 0x76, 0x34, 0x42, 0x55, 0x8f, 0x44, 0x2a, 0x6f, - 0xb1, 0xac, 0x7e, 0x9b, 0x1f, 0x9f, 0x00, 0x19, + 0x41, 0x27, 0x85, 0x25, 0x0e, 0x8e, 0xdb, 0xf3, + 0xb5, 0xdd, 0xfa, 0xb9, 0x75, 0xc0, 0x4f, 0xe8, + 0x88, 0xff, 0x04, 0x08, 0xe9, 0x0a, 0x93, 0x8f, + 0x45, 0x04, 0x03, 0x73, 0xc6, 0x24, 0x08, 0x72, }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. - 0xd3, 0x95, 0x8a, 0x56, 0xfe, 0x89, 0x86, 0x9f, - 0x47, 0x80, 0x9b, 0xea, 0x51, 0xec, 0x2b, 0x7d, - 0x76, 0xd5, 0x15, 0xde, 0x98, 0xad, 0x5d, 0x6e, - 0x79, 0xf5, 0xa4, 0x9b, 0x1b, 0x0c, 0xfa, 0x9b, + 0x47, 0xb6, 0x23, 0x3a, 0x59, 0xf7, 0x51, 0x40, + 0x41, 0x2e, 0xf1, 0xa3, 0x35, 0xa6, 0x19, 0xa1, + 0x89, 0x33, 0x0b, 0x02, 0x29, 0x3f, 0x8f, 0x35, + 0x92, 0x75, 0x80, 0x61, 0x37, 0x3e, 0x6e, 0x54, }), - Timestamp: time.Unix(0x5c238b73, 0), + Timestamp: time.Unix(0x5c34c293, 0), Bits: 0x207fffff, - Nonce: 0xdffffffffffffff9, + Nonce: 0xdffffffffffffffc, }, Transactions: []*wire.MsgTx{ { @@ -418,21 +418,21 @@ var block4 = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{ [32]byte{ // Make go vet happy. - 0x4c, 0xfb, 0xcd, 0x2b, 0x0f, 0x3c, 0xa3, 0x61, - 0x82, 0xce, 0x34, 0x39, 0x79, 0x0d, 0x22, 0x3b, - 0x94, 0xdc, 0x7b, 0x66, 0xf8, 0x62, 0xc7, 0xb2, - 0xd0, 0xfc, 0xb4, 0xf3, 0xc0, 0x7c, 0xa3, 0x63, + 0xf9, 0x3e, 0x6e, 0x3f, 0x22, 0x4b, 0x36, 0xfc, + 0x9b, 0xb4, 0xd1, 0x44, 0xbc, 0x62, 0x78, 0xa0, + 0x2f, 0xef, 0xcc, 0x16, 0xc5, 0x42, 0xbe, 0x59, + 0x22, 0xfe, 0xec, 0x01, 0x55, 0x03, 0x34, 0x62, }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. - 0xe0, 0x32, 0x30, 0x4d, 0x53, 0x1d, 0xd4, 0xe0, - 0xe1, 0xc7, 0x20, 0xf8, 0x28, 0x86, 0x45, 0x9f, - 0x5d, 0x42, 0x1f, 0x2a, 0xb5, 0xcc, 0x62, 0x7f, - 0xe7, 0xf2, 0xdd, 0x22, 0x64, 0x7c, 0xc4, 0x66, + 0x79, 0xa0, 0x0e, 0xd0, 0xaa, 0x17, 0x4e, 0xec, + 0x73, 0xd3, 0xcf, 0x13, 0x7f, 0x0d, 0x1d, 0xee, + 0x63, 0x56, 0x3c, 0x2e, 0x17, 0x19, 0x5a, 0x3e, + 0x8b, 0xd2, 0x99, 0xa4, 0xaf, 0xf9, 0xe6, 0x1e, }), - Timestamp: time.Unix(0x5c238b74, 0), + Timestamp: time.Unix(0x5c34c294, 0), Bits: 0x207fffff, - Nonce: 0xdffffffffffffffb, + Nonce: 0xdffffffffffffffa, }, Transactions: []*wire.MsgTx{ { @@ -472,25 +472,25 @@ var block5 = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{ [32]byte{ // Make go vet happy. - 0x03, 0x28, 0xad, 0x11, 0xe6, 0x8f, 0x48, 0x33, - 0x5c, 0xa8, 0xbb, 0x8c, 0x29, 0xde, 0x43, 0xd5, - 0x70, 0x8b, 0xbd, 0x1e, 0x61, 0x9d, 0xc8, 0x7d, - 0xc5, 0x52, 0x86, 0x26, 0x6b, 0x68, 0xec, 0x1f, + 0xe6, 0x08, 0x3c, 0x96, 0x4f, 0x4c, 0xb5, 0x37, + 0x2d, 0xd6, 0xe0, 0xe0, 0x85, 0x1a, 0x97, 0x0b, + 0x22, 0x91, 0x13, 0x80, 0x3b, 0xd1, 0xc8, 0x3d, + 0x8f, 0x77, 0xd5, 0xd4, 0x39, 0xc4, 0x9a, 0x09, }, [32]byte{ // Make go vet happy. - 0xcf, 0xfd, 0x63, 0x11, 0x72, 0xb7, 0xdc, 0x80, - 0x59, 0xd0, 0x35, 0x31, 0xed, 0x03, 0x89, 0x3a, - 0xe9, 0x9b, 0x74, 0xee, 0x86, 0xad, 0x3c, 0x4e, - 0x0b, 0x08, 0x46, 0xaa, 0x39, 0x30, 0xfa, 0x63, + 0xfd, 0x28, 0x66, 0x62, 0x56, 0x3e, 0xf0, 0x33, + 0x85, 0xca, 0xf6, 0x96, 0x0d, 0x3a, 0x73, 0xd1, + 0x3b, 0xb8, 0xa0, 0xda, 0xae, 0x4d, 0xdc, 0xa6, + 0x56, 0x82, 0xfd, 0x3b, 0xa0, 0x92, 0x27, 0x38, }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. - 0x8e, 0xb2, 0xf8, 0x31, 0xec, 0x11, 0xc2, 0x22, - 0xd1, 0x31, 0x47, 0xf0, 0xbb, 0x48, 0x74, 0xce, - 0x4a, 0x39, 0x25, 0x99, 0xa7, 0x1c, 0x8c, 0x83, - 0x98, 0x8d, 0x66, 0xc5, 0x94, 0xa9, 0xf1, 0x50, + 0x29, 0xc6, 0xbc, 0xd9, 0xac, 0x1d, 0x4a, 0x5e, + 0xb0, 0x71, 0xfd, 0xac, 0xde, 0x39, 0xc0, 0x9c, + 0x90, 0xb8, 0x22, 0xde, 0x2d, 0x76, 0x49, 0xab, + 0x80, 0xdc, 0x77, 0xa8, 0xd7, 0x75, 0x40, 0x18, }), - Timestamp: time.Unix(0x5c238b75, 0), + Timestamp: time.Unix(0x5c34c295, 0), Bits: 0x207fffff, Nonce: 0xdffffffffffffffa, }, diff --git a/blockdag/subnetworks.go b/blockdag/subnetworks.go index 7182888f3..4a90b5285 100644 --- a/blockdag/subnetworks.go +++ b/blockdag/subnetworks.go @@ -4,8 +4,10 @@ import ( "bytes" "encoding/binary" "fmt" + "github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/database" + "github.com/daglabs/btcd/util/subnetworkid" "github.com/daglabs/btcd/wire" ) @@ -98,7 +100,7 @@ func (dag *BlockDAG) registerPendingSubNetworksInBlock(dbTx database.Tx, blockHa // subNetwork returns a registered-and-finalized sub-network. If the sub-network // does not exist this method returns an error. -func (dag *BlockDAG) subNetwork(subNetworkID uint64) (*subNetwork, error) { +func (dag *BlockDAG) subNetwork(subNetworkID subnetworkid.SubNetworkID) (*subNetwork, error) { var sNet *subNetwork var err error dbErr := dag.db.View(func(dbTx database.Tx) error { @@ -117,7 +119,7 @@ func (dag *BlockDAG) subNetwork(subNetworkID uint64) (*subNetwork, error) { // GasLimit returns the gas limit of a registered-and-finalized sub-network. If // the sub-network does not exist this method returns an error. -func (dag *BlockDAG) GasLimit(subNetworkID uint64) (uint64, error) { +func (dag *BlockDAG) GasLimit(subNetworkID subnetworkid.SubNetworkID) (uint64, error) { sNet, err := dag.subNetwork(subNetworkID) if err != nil { return 0, err @@ -281,14 +283,10 @@ func dbRegisterSubNetwork(dbTx database.Tx, subNetworkID uint64, txHash daghash. return nil } -func dbGetSubNetwork(dbTx database.Tx, subNetworkID uint64) (*subNetwork, error) { - // Serialize the sub-network ID - subNetworkIDBytes := make([]byte, 8) - byteOrder.PutUint64(subNetworkIDBytes, subNetworkID) - +func dbGetSubNetwork(dbTx database.Tx, subNetworkID subnetworkid.SubNetworkID) (*subNetwork, error) { // Get the sub-network bucket := dbTx.Metadata().Bucket(subNetworksBucketName) - serializedSubNetwork := bucket.Get(subNetworkIDBytes) + serializedSubNetwork := bucket.Get(subNetworkID[:]) if serializedSubNetwork == nil { return nil, fmt.Errorf("sub-network '%d' not found", subNetworkID) } diff --git a/blockdag/testdata/blk_0_to_4.dat b/blockdag/testdata/blk_0_to_4.dat index 50287849050c0d5d35095c12e150bd9b5571f7b2..abc32a798ddee5cb4927595f85c74c7ab1ea539b 100644 GIT binary patch delta 919 zcmdnVJCo1x=e{jBl^7WqfQW%1szxn@*DX8VOGop+{?Y|&=Unp7TPgNyYfzlSqRef* zF}pUK#DLWO|6i~0^FJ8epXhjZat|XjHhnKr@CCx=TKIf?8AO@$pNXr z@^8X5Y~7b~A6mQ;I_srbt8^iLzPtC7`aeF3EpP6;_m=%puD*X#yJ?8Hlhr=4^8E;l z{y{9VpXjJHc_pI*$g(7mWvigBX57&Dw2x`&(%47yPqaE8;PczlBlvf((uWtdVeihH z^sSJ4q#N6M;h?J_%f@28N1ZohPuJ(I*~h-bKqO(>3(F+)85KyD{f1aJpJ{Rfqt@h7 zCVP-|^xwYB&a+vHl}O%(g)zk20xU@0p7>VYNS(*>@%QAjEP)_z zM}cA+?(KhVADAuTy9I7AO0BsqGmjy(BSNj2GcBYgK>wiv?{>>GJ(j%k_8O8CLVSO| zxVCF!+BsbzsdF9^gT;>@=UOhoN2Ux@-AL4)0XC r$fQuWiDR<(V|V*~H`bX{w63nd*RdyK($%#}Yk#a3*?h}R2&;Di;#iA` delta 893 zcmbQqx0BcL=e{jB#TXeFfQW%1Q(kY5r%=ezd$Ro(raG{HxFzk=V#7YAJ?k>xsrED8 zJ2%%T$AHxR|6i~0`#%`WpXhiu5oE|=pg717MiVjd*4Xcr_wJZ~2%kJRU+L-p1$M{n z0=_QP;?nbAJ>;HgBD;LkB(5hBMw&lfc%GkD;4*dAb?poen#3w&s6`I`3 zWM2>V5FrPHLL}S6z?Dgn;dsE3&XdfU7LOc__~+bt`}~UM_0Rtc+ylezxGj>fTH3{= zz<lMGB^?c4JV1Mu8{QBv~yXv6zWLj37+_N*HW?SEa$$QuW zqdpGL1h^7Eg`2Uv|J+p|Eu`E=4r?(%{QUnRass7*d^ zpcr6qSVV|>%9_yQf_mLoH?o7gndNTa!la-OqAytV_or0!irWPfIeL0dZREJ2T(`6# z+c!-8{ru!qCI#1N$=ZzJo5U`Dvk2L|O*?cw>*=ohd#>DDcy>?w*E~fD6kqmE-pdw% z8ns)JGm{>ce95xEkYl+!`@^%F3l##(euS(#@$$un&EHogYAKq>E1W&O_P}e7Gl>g> z+Dx`wv;27Bf)wZe@@9oT_ rpdBewC=z$jOwQN%=gCv7b#gNnyN3N`E?l^gIq~Wow+AR521P3X<5`nZ diff --git a/blockdag/testdata/blk_3A.dat b/blockdag/testdata/blk_3A.dat index 1af686a13499fc7aa2cb4cd8fac3afbc7e5e808f..c6c6b5c646945f77ad37d25efd1497046a2c2d0a 100644 GIT binary patch delta 236 zcmbQmyqP)b=e{jBS2Hp&01*RYe#9Li+1j|JmzQ*1;?kGbI&gJX&8b(n7caDX+PB|o z5wnWgJnK+#?~fiE>l!wCow!_4E6Z|PFk^0U?MKhg8{79(?l*}6n#1t_f4#!biBW|U zD|qU`22Xq|Z=}v+c(aHlyXKuuvi54J_O7eXHAH8bsL#9hdGkDwrfd%bS0+Vcy@zx-dDFeZic9WA#MmjrE!P~6TTw*9Dudqsn~ kxeIG~(RQaqxBMNZjEYRlij#YGM$~NUTQJ#^F%aks0NX-fsQ>@~ delta 230 zcmVr0jPx|TmS$70RR7gAp4P8 zaen~-0005ylF18qaM1M_^cW_S&oCiSFvAoQ3zV!?#}O`z)v*Tv0001LM=(SJARtsP z5pw|LI=kev=rWISl{**DL(`4+i@u KCT2~n-~j;1A~wnZ delta 105 zcmcc4c$zWs=e{jB4>K?@FoH0*VcsXU*320vIDZ5z*tEJm=Iib)n|*&RiTr3?JoDI; zlB6BV-HgFgnIDPEX{7A_8@!s~;l-(IW$rdkJv-Osr_J*ft;#V#a~S^ruUGi<9}MPC HOw0lR28A@G diff --git a/blockdag/testdata/blk_3C.dat b/blockdag/testdata/blk_3C.dat index 53e790c5505de523d0f3f5732516140e910dd755..f6004aced123599f6bbeaa79f4f7abf9abc85c8c 100644 GIT binary patch delta 141 zcmV;80CNB90rvra`M$K-?*IS*0RR910YBrPHK}(h4shD!|p6e9G$EqoF?Kj=wsh14zbtiY^p=^04R1yj7n~ v4?g}9WLx-bHekR-d!+O#?s>m7TmS$70RR7gAp8IS|Ns92|DTb8YLS=>KDbA~ delta 138 zcmV;50CoTO0qX&O`M$K-;{X5v0RR910t+#2@&<)zn8*qEP@uA_hg|i$w6jh6q*?Jh zbD74JbnvH&WdHn6JLQq%A#%uiYeRk@u@tv4tlX!sfl;?g$PK}uq4<$jYGpg9cx|JN)0{0|2A zCnjc1tl+5!na?!wt-O&skKxTCmh75$Hp$wnrP{l$KGzVPWuiXs+UL#lKzg%13|yHM z8Fn6dxqqF+tE11NJeQi9ehuC;N&HmxlHiwWVFJmv{dbI*6bxe0jA#DXp%i&C`Y(HX yU1O)|N}JPbYhrgC(rIC8`=-pO$h53Dxo2lY&9=S;lf4+_REe>kVd4a9pnCzveSVPu delta 278 zcmaFBe1bXg=e{jB4=^$?01*Qtw_)BVw${uUCpdouEZDTVJ?87~Et`FREs6YST|D#H zl#&t=ty;7HvUlRcLk`qUnId@2d3xCu{tY*+1UBmCHX1OkXjP5@n#1t_f4#z=|6nkG zVq#W3$Z)2olTLD%7hL!%@kK&y@_7Tr0E5FKLfli%O{?9i%ba!@!kEkzq~e z^sJD_um1gxh`6%6%eiUSA8WTIAGWPGomza5;mtEOCIybY6Y~~I?`m?7IKF-M*Zz~% uPuBlBuGz@?|Khr;Z+5YV7!{e86({%XjHubxw_tJ@qns)+)-z0;U=09}tbPyx diff --git a/blockdag/validate.go b/blockdag/validate.go index bf2b30d78..a0fe2b292 100644 --- a/blockdag/validate.go +++ b/blockdag/validate.go @@ -16,6 +16,7 @@ import ( "github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/txscript" "github.com/daglabs/btcd/util" + "github.com/daglabs/btcd/util/subnetworkid" "github.com/daglabs/btcd/wire" ) @@ -496,7 +497,7 @@ func checkBlockSanity(block *util.Block, powLimit *big.Int, timeSource MedianTim "index %d", i+1) return ruleError(ErrMultipleCoinbases, str) } - if tx.MsgTx().SubNetworkID < transactions[i].MsgTx().SubNetworkID { + if subnetworkid.Less(&tx.MsgTx().SubNetworkID, &transactions[i].MsgTx().SubNetworkID) { return ruleError(ErrTransactionsNotSorted, "transactions must be sorted by subnetwork") } } diff --git a/blockdag/validate_test.go b/blockdag/validate_test.go index 056a2526b..e1edecdf2 100644 --- a/blockdag/validate_test.go +++ b/blockdag/validate_test.go @@ -13,6 +13,7 @@ import ( "github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/util" + "github.com/daglabs/btcd/util/subnetworkid" "github.com/daglabs/btcd/wire" ) @@ -640,14 +641,14 @@ var Block100000 = wire.MsgBlock{ }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. - 0x0b, 0x79, 0xf5, 0x29, 0x6d, 0x1c, 0xaa, 0x90, - 0x2f, 0x01, 0xd4, 0x83, 0x9b, 0x2a, 0x04, 0x5e, - 0xa0, 0x69, 0x2d, 0x16, 0xb5, 0xd7, 0xe4, 0xf3, - 0xcd, 0xc7, 0xc9, 0xaf, 0xfb, 0xd2, 0x1b, 0x85, + 0xe8, 0x09, 0xa1, 0x6c, 0xf2, 0xfb, 0xb1, 0x2d, + 0xff, 0xff, 0x7d, 0x0f, 0x5b, 0xdc, 0xaa, 0xfd, + 0xf1, 0xe4, 0x92, 0x23, 0x1b, 0x8c, 0xbf, 0x6a, + 0x28, 0x52, 0x10, 0x9f, 0x93, 0x96, 0x1f, 0x25, }), Timestamp: time.Unix(0x5c22330f, 0), Bits: 0x207fffff, - Nonce: 0xdffffffffffffffc, + Nonce: 1, }, Transactions: []*wire.MsgTx{ { @@ -1014,7 +1015,7 @@ var BlockWithWrongTxOrder = wire.MsgBlock{ }, }, LockTime: 0, - SubNetworkID: wire.SubNetworkDAGCoin + 10, + SubNetworkID: subnetworkid.SubNetworkID{11}, }, { Version: 1, diff --git a/config/config.go b/config/config.go index 27b417f27..3a68ea936 100644 --- a/config/config.go +++ b/config/config.go @@ -28,6 +28,7 @@ import ( "github.com/daglabs/btcd/mempool" "github.com/daglabs/btcd/util" "github.com/daglabs/btcd/util/network" + "github.com/daglabs/btcd/util/subnetworkid" "github.com/daglabs/btcd/version" "github.com/daglabs/btcd/wire" "github.com/jessevdk/go-flags" @@ -165,7 +166,7 @@ type configFlags struct { DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."` RelayNonStd bool `long:"relaynonstd" description:"Relay non-standard transactions regardless of the default settings for the active network."` RejectNonStd bool `long:"rejectnonstd" description:"Reject non-standard transactions regardless of the default settings for the active network."` - SubNetwork uint64 `long:"subnetwork" description:"If subnetwork > 0, than node will request and process only payloads from specified subnetwork. And if subnetwork is 0, than payloads of all subnetworks are processed. Subnetworks 3 through 255 are reserved for future use and are currently not allowed."` + SubNetwork string `string:"subnetwork" description:"If subnetwork != 0, than node will request and process only payloads from specified subnetwork. And if subnetwork is 0, than payloads of all subnetworks are processed. Subnetworks 3 through 255 are reserved for future use and are currently not allowed."` } // Config defines the configuration options for btcd. @@ -180,6 +181,7 @@ type Config struct { MiningAddrs []util.Address MinRelayTxFee util.Amount Whitelists []*net.IPNet + SubNetwork *subnetworkid.SubNetworkID } // serviceOptions defines the configuration options for the daemon as a service on @@ -751,16 +753,15 @@ func loadConfig() (*Config, []string, error) { cfg.MiningAddrs = append(cfg.MiningAddrs, addr) } - if cfg.SubNetwork >= wire.SubNetworkReservedFirst && cfg.SubNetwork < wire.SubNetworkUnreservedFirst { - str := "%s: subnetworkID %d is reserved for future use, and nodes can not run in it " - err := fmt.Errorf(str, funcName, cfg.SubNetwork) - fmt.Fprintln(os.Stderr, err) - fmt.Fprintln(os.Stderr, usageMessage) - return nil, nil, err + if cfg.configFlags.SubNetwork != "" { + cfg.SubNetwork, err = subnetworkid.NewIDFromStr(cfg.configFlags.SubNetwork) + if err != nil { + return nil, nil, err + } } // Check that 'generate' and 'subnetwork' flags do not conflict - if cfg.Generate && cfg.SubNetwork != wire.SubNetworkSupportsAll { + if cfg.Generate && *cfg.SubNetwork != wire.SubNetworkSupportsAll { str := "%s: both generate flag and subnetwork filtering are set " err := fmt.Errorf(str, funcName) fmt.Fprintln(os.Stderr, err) diff --git a/config/config_test.go b/config/config_test.go index 7d8d73d37..be08219c5 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -8,6 +8,7 @@ import ( "runtime" "testing" + "github.com/daglabs/btcd/util/subnetworkid" "github.com/daglabs/btcd/wire" ) @@ -75,15 +76,8 @@ func TestCreateDefaultConfigFile(t *testing.T) { // TestConstants makes sure that all constants hard-coded into the help text were not modified. func TestConstants(t *testing.T) { - if wire.SubNetworkSupportsAll != 0 { + zero := subnetworkid.SubNetworkID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + if wire.SubNetworkSupportsAll != zero { t.Errorf("wire.SubNetworkSupportsAll value was changed from 0, therefore you probably need to update the help text for SubNetwork") } - - if wire.SubNetworkReservedFirst != 3 { - t.Errorf("wire.SubNetworkReservedFirst value was changed from 0, therefore you probably need to update the help text for SubNetwork") - } - - if wire.SubNetworkUnreservedFirst != 256 { - t.Errorf("wire.SubNetworkUnreservedFirst value was changed from 0, therefore you probably need to update the help text for SubNetwork") - } } diff --git a/dagconfig/genesis.go b/dagconfig/genesis.go index 97a6b077a..4004c2abe 100644 --- a/dagconfig/genesis.go +++ b/dagconfig/genesis.go @@ -60,19 +60,19 @@ var genesisCoinbaseTx = wire.MsgTx{ // genesisHash is the hash of the first block in the block chain for the main // network (genesis block). var genesisHash = daghash.Hash([daghash.HashSize]byte{ // Make go vet happy. - 0x34, 0x16, 0x17, 0x85, 0x5d, 0xf7, 0x79, 0xde, - 0xdc, 0x37, 0xf0, 0x57, 0x93, 0x9d, 0x6f, 0x22, - 0xe5, 0xff, 0xa0, 0x3e, 0xc7, 0x3e, 0x50, 0xf5, - 0xa1, 0x2a, 0x0a, 0x2e, 0x48, 0x05, 0xc2, 0x47, + 0xca, 0xd9, 0x5f, 0x65, 0x44, 0xd4, 0x2f, 0x08, + 0x23, 0x22, 0x93, 0x4c, 0x07, 0xd9, 0xa4, 0xc0, + 0x1a, 0x51, 0x77, 0xf6, 0x13, 0x7c, 0x06, 0x8b, + 0xd2, 0x6d, 0xe1, 0x38, 0xea, 0x12, 0xcd, 0x4a, }) // genesisMerkleRoot is the hash of the first transaction in the genesis block // for the main network. var genesisMerkleRoot = daghash.Hash([daghash.HashSize]byte{ // Make go vet happy. - 0x79, 0x6e, 0xd7, 0x12, 0x58, 0xea, 0x3f, 0x88, - 0xa1, 0xfa, 0x7a, 0x67, 0x2b, 0x68, 0x76, 0x6b, - 0x39, 0x6b, 0x7d, 0x15, 0x6b, 0x1a, 0xb1, 0x96, - 0xe2, 0x17, 0x2c, 0x4a, 0x6a, 0xad, 0x72, 0x96, + 0x5a, 0x7c, 0x26, 0x54, 0x0d, 0x46, 0x6b, 0x5f, + 0x4a, 0x2c, 0x29, 0xff, 0x2f, 0xa5, 0xa0, 0xad, + 0x9c, 0xd2, 0x4f, 0x6e, 0xa9, 0x16, 0xfa, 0xb5, + 0x52, 0x5e, 0x40, 0xa2, 0x69, 0xb6, 0x8d, 0x5c, }) // genesisBlock defines the genesis block of the block chain which serves as the @@ -82,9 +82,9 @@ var genesisBlock = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{}, MerkleRoot: genesisMerkleRoot, - Timestamp: time.Unix(0x5c238413, 0), + Timestamp: time.Unix(0x5c34b3ba, 0), Bits: 0x207fffff, - Nonce: 0x00000001, + Nonce: 0xdffffffffffffff9, }, Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, } @@ -92,10 +92,10 @@ var genesisBlock = wire.MsgBlock{ // regTestGenesisHash is the hash of the first block in the block chain for the // regression test network (genesis block). var regTestGenesisHash = daghash.Hash([daghash.HashSize]byte{ // Make go vet happy. - 0x34, 0x16, 0x17, 0x85, 0x5d, 0xf7, 0x79, 0xde, - 0xdc, 0x37, 0xf0, 0x57, 0x93, 0x9d, 0x6f, 0x22, - 0xe5, 0xff, 0xa0, 0x3e, 0xc7, 0x3e, 0x50, 0xf5, - 0xa1, 0x2a, 0x0a, 0x2e, 0x48, 0x05, 0xc2, 0x47, + 0xca, 0xd9, 0x5f, 0x65, 0x44, 0xd4, 0x2f, 0x08, + 0x23, 0x22, 0x93, 0x4c, 0x07, 0xd9, 0xa4, 0xc0, + 0x1a, 0x51, 0x77, 0xf6, 0x13, 0x7c, 0x06, 0x8b, + 0xd2, 0x6d, 0xe1, 0x38, 0xea, 0x12, 0xcd, 0x4a, }) // regTestGenesisMerkleRoot is the hash of the first transaction in the genesis @@ -110,9 +110,9 @@ var regTestGenesisBlock = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{}, MerkleRoot: genesisMerkleRoot, - Timestamp: time.Unix(0x5c238413, 0), + Timestamp: time.Unix(0x5c34b3ba, 0), Bits: 0x207fffff, - Nonce: 0x00000001, + Nonce: 0xdffffffffffffff9, }, Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, } @@ -120,10 +120,10 @@ var regTestGenesisBlock = wire.MsgBlock{ // testNet3GenesisHash is the hash of the first block in the block chain for the // test network (version 3). var testNet3GenesisHash = daghash.Hash([daghash.HashSize]byte{ // Make go vet happy. - 0x34, 0x16, 0x17, 0x85, 0x5d, 0xf7, 0x79, 0xde, - 0xdc, 0x37, 0xf0, 0x57, 0x93, 0x9d, 0x6f, 0x22, - 0xe5, 0xff, 0xa0, 0x3e, 0xc7, 0x3e, 0x50, 0xf5, - 0xa1, 0x2a, 0x0a, 0x2e, 0x48, 0x05, 0xc2, 0x47, + 0xca, 0xd9, 0x5f, 0x65, 0x44, 0xd4, 0x2f, 0x08, + 0x23, 0x22, 0x93, 0x4c, 0x07, 0xd9, 0xa4, 0xc0, + 0x1a, 0x51, 0x77, 0xf6, 0x13, 0x7c, 0x06, 0x8b, + 0xd2, 0x6d, 0xe1, 0x38, 0xea, 0x12, 0xcd, 0x4a, }) // testNet3GenesisMerkleRoot is the hash of the first transaction in the genesis @@ -138,9 +138,9 @@ var testNet3GenesisBlock = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{}, MerkleRoot: genesisMerkleRoot, - Timestamp: time.Unix(0x5c238413, 0), + Timestamp: time.Unix(0x5c34b3ba, 0), Bits: 0x207fffff, - Nonce: 0x00000001, + Nonce: 0xdffffffffffffff9, }, Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, } @@ -148,10 +148,10 @@ var testNet3GenesisBlock = wire.MsgBlock{ // simNetGenesisHash is the hash of the first block in the block chain for the // simulation test network. var simNetGenesisHash = daghash.Hash([daghash.HashSize]byte{ // Make go vet happy. - 0x34, 0x16, 0x17, 0x85, 0x5d, 0xf7, 0x79, 0xde, - 0xdc, 0x37, 0xf0, 0x57, 0x93, 0x9d, 0x6f, 0x22, - 0xe5, 0xff, 0xa0, 0x3e, 0xc7, 0x3e, 0x50, 0xf5, - 0xa1, 0x2a, 0x0a, 0x2e, 0x48, 0x05, 0xc2, 0x47, + 0xca, 0xd9, 0x5f, 0x65, 0x44, 0xd4, 0x2f, 0x08, + 0x23, 0x22, 0x93, 0x4c, 0x07, 0xd9, 0xa4, 0xc0, + 0x1a, 0x51, 0x77, 0xf6, 0x13, 0x7c, 0x06, 0x8b, + 0xd2, 0x6d, 0xe1, 0x38, 0xea, 0x12, 0xcd, 0x4a, }) // simNetGenesisMerkleRoot is the hash of the first transaction in the genesis @@ -166,9 +166,9 @@ var simNetGenesisBlock = wire.MsgBlock{ Version: 1, ParentHashes: []daghash.Hash{}, MerkleRoot: genesisMerkleRoot, - Timestamp: time.Unix(0x5c238413, 0), + Timestamp: time.Unix(0x5c34b3ba, 0), Bits: 0x207fffff, - Nonce: 0x00000001, + Nonce: 0xdffffffffffffff9, }, Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, } diff --git a/dagconfig/genesis_test.go b/dagconfig/genesis_test.go index 860d97342..fd1952f59 100644 --- a/dagconfig/genesis_test.go +++ b/dagconfig/genesis_test.go @@ -121,14 +121,14 @@ func TestSimNetGenesisBlock(t *testing.T) { // genesisBlockBytes are the wire encoded bytes for the genesis block of the // main network as of protocol version 60002. var genesisBlockBytes = []byte{ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x6e, 0xd7, /* |.....yn.| */ - 0x12, 0x58, 0xea, 0x3f, 0x88, 0xa1, 0xfa, 0x7a, /* |.X.?...z| */ - 0x67, 0x2b, 0x68, 0x76, 0x6b, 0x39, 0x6b, 0x7d, /* |g+hvk9k}| */ - 0x15, 0x6b, 0x1a, 0xb1, 0x96, 0xe2, 0x17, 0x2c, /* |.k.....,| */ - 0x4a, 0x6a, 0xad, 0x72, 0x96, 0x13, 0x84, 0x23, /* |Jj.r...#| */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x7c, 0x26, /* |.....Z|&| */ + 0x54, 0x0d, 0x46, 0x6b, 0x5f, 0x4a, 0x2c, 0x29, /* |T.Fk_J,)| */ + 0xff, 0x2f, 0xa5, 0xa0, 0xad, 0x9c, 0xd2, 0x4f, /* |./.....O| */ + 0x6e, 0xa9, 0x16, 0xfa, 0xb5, 0x52, 0x5e, 0x40, /* |n....R^@| */ + 0xa2, 0x69, 0xb6, 0x8d, 0x5c, 0xba, 0xb3, 0x34, /* |.i..\..4| */ 0x5c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, /* |\.......| */ - 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* | .......| */ - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ + 0x20, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* | .......| */ + 0xdf, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ @@ -155,20 +155,22 @@ var genesisBlockBytes = []byte{ 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, /* |....W.Lp| */ 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, 0xac, 0x00, 0x00, /* |+k.._...| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |......| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, /* |..| */ } // regTestGenesisBlockBytes are the wire encoded bytes for the genesis block of // the regression test network as of protocol version 60002. var regTestGenesisBlockBytes = []byte{ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x6e, 0xd7, /* |.....yn.| */ - 0x12, 0x58, 0xea, 0x3f, 0x88, 0xa1, 0xfa, 0x7a, /* |.X.?...z| */ - 0x67, 0x2b, 0x68, 0x76, 0x6b, 0x39, 0x6b, 0x7d, /* |g+hvk9k}| */ - 0x15, 0x6b, 0x1a, 0xb1, 0x96, 0xe2, 0x17, 0x2c, /* |.k.....,| */ - 0x4a, 0x6a, 0xad, 0x72, 0x96, 0x13, 0x84, 0x23, /* |Jj.r...#| */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x7c, 0x26, /* |.....Z|&| */ + 0x54, 0x0d, 0x46, 0x6b, 0x5f, 0x4a, 0x2c, 0x29, /* |T.Fk_J,)| */ + 0xff, 0x2f, 0xa5, 0xa0, 0xad, 0x9c, 0xd2, 0x4f, /* |./.....O| */ + 0x6e, 0xa9, 0x16, 0xfa, 0xb5, 0x52, 0x5e, 0x40, /* |n....R^@| */ + 0xa2, 0x69, 0xb6, 0x8d, 0x5c, 0xba, 0xb3, 0x34, /* |.i..\..4| */ 0x5c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, /* |\.......| */ - 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* | .......| */ - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ + 0x20, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* | .......| */ + 0xdf, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ @@ -195,20 +197,22 @@ var regTestGenesisBlockBytes = []byte{ 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, /* |....W.Lp| */ 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, 0xac, 0x00, 0x00, /* |+k.._...| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |......| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, /* |..| */ } // testNet3GenesisBlockBytes are the wire encoded bytes for the genesis block of // the test network (version 3) as of protocol version 60002. var testNet3GenesisBlockBytes = []byte{ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x6e, 0xd7, /* |.....yn.| */ - 0x12, 0x58, 0xea, 0x3f, 0x88, 0xa1, 0xfa, 0x7a, /* |.X.?...z| */ - 0x67, 0x2b, 0x68, 0x76, 0x6b, 0x39, 0x6b, 0x7d, /* |g+hvk9k}| */ - 0x15, 0x6b, 0x1a, 0xb1, 0x96, 0xe2, 0x17, 0x2c, /* |.k.....,| */ - 0x4a, 0x6a, 0xad, 0x72, 0x96, 0x13, 0x84, 0x23, /* |Jj.r...#| */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x7c, 0x26, /* |.....Z|&| */ + 0x54, 0x0d, 0x46, 0x6b, 0x5f, 0x4a, 0x2c, 0x29, /* |T.Fk_J,)| */ + 0xff, 0x2f, 0xa5, 0xa0, 0xad, 0x9c, 0xd2, 0x4f, /* |./.....O| */ + 0x6e, 0xa9, 0x16, 0xfa, 0xb5, 0x52, 0x5e, 0x40, /* |n....R^@| */ + 0xa2, 0x69, 0xb6, 0x8d, 0x5c, 0xba, 0xb3, 0x34, /* |.i..\..4| */ 0x5c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, /* |\.......| */ - 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* | .......| */ - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ + 0x20, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* | .......| */ + 0xdf, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ @@ -235,20 +239,22 @@ var testNet3GenesisBlockBytes = []byte{ 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, /* |....W.Lp| */ 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, 0xac, 0x00, 0x00, /* |+k.._...| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |......| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, /* |..| */ } // simNetGenesisBlockBytes are the wire encoded bytes for the genesis block of // the simulation test network as of protocol version 70002. var simNetGenesisBlockBytes = []byte{ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x6e, 0xd7, /* |.....yn.| */ - 0x12, 0x58, 0xea, 0x3f, 0x88, 0xa1, 0xfa, 0x7a, /* |.X.?...z| */ - 0x67, 0x2b, 0x68, 0x76, 0x6b, 0x39, 0x6b, 0x7d, /* |g+hvk9k}| */ - 0x15, 0x6b, 0x1a, 0xb1, 0x96, 0xe2, 0x17, 0x2c, /* |.k.....,| */ - 0x4a, 0x6a, 0xad, 0x72, 0x96, 0x13, 0x84, 0x23, /* |Jj.r...#| */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x7c, 0x26, /* |.....Z|&| */ + 0x54, 0x0d, 0x46, 0x6b, 0x5f, 0x4a, 0x2c, 0x29, /* |T.Fk_J,)| */ + 0xff, 0x2f, 0xa5, 0xa0, 0xad, 0x9c, 0xd2, 0x4f, /* |./.....O| */ + 0x6e, 0xa9, 0x16, 0xfa, 0xb5, 0x52, 0x5e, 0x40, /* |n....R^@| */ + 0xa2, 0x69, 0xb6, 0x8d, 0x5c, 0xba, 0xb3, 0x34, /* |.i..\..4| */ 0x5c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, /* |\.......| */ - 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* | .......| */ - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ + 0x20, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* | .......| */ + 0xdf, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ @@ -275,5 +281,7 @@ var simNetGenesisBlockBytes = []byte{ 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, /* |....W.Lp| */ 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, 0xac, 0x00, 0x00, /* |+k.._...| */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* |........| */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |......| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, /* |..| */ } diff --git a/database/example_test.go b/database/example_test.go index f6844bd1b..f0f882fb0 100644 --- a/database/example_test.go +++ b/database/example_test.go @@ -175,5 +175,5 @@ func Example_blockStorageAndRetrieval() { fmt.Printf("Serialized block size: %d bytes\n", len(loadedBlockBytes)) // Output: - // Serialized block size: 278 bytes + // Serialized block size: 290 bytes } diff --git a/database/testdata/blocks1-256.bz2 b/database/testdata/blocks1-256.bz2 index f7da29094fa288759522c7aa7ad1c6543a461de8..fc31bb9f1c93e6f61952c6d04f38746a82cf5632 100644 GIT binary patch literal 9945 zcmai3WkX!O5?-u06fIud-EE;13dM_4tT-(0zDRL*cXx;4Qrs!-?y|V+-S-#VoRfUW z$xNPkl8Maus%0*~A@-A2<>#q05eXnP;QjxmO`bW>kjhG*<)x28OH*(xc>Prr zzYjNZdIS|0(TLL0W(9IIq!JW$$B*O8@|JE9ad2{)cU!Q_%}7Vm8c*fsaxcpfr6Y3? zWaUrE^NQmj0NEob^03rYE_2e{5xB3iW)W{E8 zPlnuM0+8I_Tp%s7U%vR48FE@sZjtXa5V=S)E5vx2;n>4OI1N<9uqjXQeV{lDSg=fs zBNi{OI7KCY%#jC*m&*!GxYD1^LYJp2-OQO)Q=E}2J@%B7luMN(0`aEdFlk$Xr+%PW#k3#a*men%#}%B2(+00}^n(F~hP#R)@K);x+zsfxHa{Ty6V+*vpb zyR+7`{Xn{++^6`NAB<&w9E9jNlICzS);Ur+@<4e-5+0!`mg{W z!eE%f?UVtad%13Z1`J$Zt)#^QhA%Y?Fu)#Pd2GJ~WgOEVfLR8_D`o6}0*3FLVPdR5 zKH~bzH6TzR=@-D0|6_Ll4)Z$(&V)9tc=cpu@L3#G_A)UxyLD7)9~QZX*WuOhE#+uL z)$qw8MX#%6q{%O#Z2IC3Vx|~A-fi{r5lxRRl15={)0h!}eH+0StP>8HHKBBy*}z=- ztlhuW{u-^pU=L`OGN~lTx0vOw{09K^Cps<7Hkx&;DY)MGKXz?$mf`C2r`M~ej(I|v)Gh@h~AZk=|>NN>tzXKZyPInGYy##!yR7ToY%2% z$5U0Xl0VxQS~pb^;p?_b+#skfFxj6eHp&CzXwb%pFqnt(iq_cXe_zz|+)Yp&nrYM2 zHG02MFvfk(%(mJD008hEL^Z$VRr$5mBBDq%PozTL;bp-FlGX0cmDX{@Z#{FCd^{Rc zB5EGl`{$j0!g2NMZM3#9T!|a(ChgZ1%BNP`zr;~(CIA4KE2@W)Z8~+Q>-3zME$cD2 z*yE$jkGH>HqbJl<59q2;WMjIgHaXPM3a6cKbC>g#o4=-q5*?LnWMl6ftNP$XdiJn_ zgQZGF>2ud40*uQ&RNQ;|RBH=k!Rjq9a^8V$DxWQ*qI2`3mv6MvtJ20+-E2Au@UBQn zSg*yo4CXAAjE$-H3SKbFlWWuycTicgtN;Mm+D<~}YIjdd1N?tcJZq62qg900kB@$lRiOxeQxWG|m{1latD3oQotU~fP7002 zWP*676ZerkAO!0!#Sh*;M3f+6?DX|tXd9Ov<`{89A*^S+dF@cYaRO|7nEjXYR_@_v=) z%L&HgYVzKp{HAPms-UWkp#RWRAR(iQ)QF9f!h4&Pb3jpeDob~V9m@Gd zYC|?%91uNerU#!l~{6m_-aq79q>&4h4aONwQ0>^ ze`@U9N0%Q#yR^M%%wANm;`5f%un`zZ7oWKD+uxAhwS9;{2Jm2`&_RS9HMy{V!H}V) zlP62cq$%XVm#+YK$M{D!HRNsFWI2m@d2`d|3jiQ2XMTmFtJc~?l&{*zLGY+5OwD=~ z3cfb^z?b?vey#sdgd7F3equ1C>q!35^)2Q@Cq0}mj2U1WUS{nLPxNrExu92@?Vv}5L%&L&eRzPs!*8h!-4t z_?$AWC+JLVKLs;IO}bl4$|@nkX=B5+{Mc}zhYXi%r{ZORXGP}NCuGNpeO@{L$PQ)4 z8>R7ShALRLGg{7GX;>?x+uE6`b{Q0`<0;f3&AEEbr@SbHM*KIi5%9l8kcNC#I<^pq zk9Z%`b*^G~gH@zn4PMmaDLMLrQ$sH z<*VsUUh2sv0D!y--i_C}jYX8qHrPMZbB+rdp5HA&ZK za8h+OMk}bP=X`$LZLn(Kqdb`VR^bb6YQUjFAYbd_GcXz?VYG9$e#6iww)c@XK+H?9 z-ugbUA)lFoESEVAzGl;or|CZdxXsqOR-7Pb%P9QrG~8IkclT{*E#nEd=hJe;`vh)> zYe~DJ*QLwsAL8fVX?F_(DR3t^B5O>xcb&x?A`U_gr5fdwItHJFISje6{PNSsbdD6T zLY*P=(HNlXq+GT=cYgI^=JQ#oQUJS1Wj3TcY|m|W_0D32je^QxSp1-(R-i08w-7Mw z4K7<4f+<_IHnHk-($yY{f3s_N<%`C&Zn6Tqkz;Pc*8T&Wfr{R2jp(?=(>oXc(-Cf7cu;GHc}v-8 zPM5|d$-Eu2o@h9~8n*0Jr)$H&Qv1x#a^+L~vmvp8;OeTYkgpSmeVn{Jb&re%(yL_Djo?E z;;!)FpT2zBOLap=SGd}&x>Phbu0{+lin4bH01pqnJK4L7lIK6IR(nlOFsoId$42SN zY`!4Cz|ocdM=(l1!cJgXK+61_r*H(?8Pic4I5TtogX!FXj_BMO2O0L<`&NGt<*}Mu z9VH*;4NdvX%hGP<-GB68O-)h7uuy+#p;!-!C9gdH)c9yQwb7I8#Xn@*#Sr5;=pDv% zGtDiZOm$#{=bR_KeWL?vKo#(2*js+|+eW0>RGaD7y9YP82U{)Bvz9v9xbwx^Bm|Wh zG!koa%@t5MNAa>VBwn(k4c@Zxb#{2oZ84F-Hq9e)_d3to6IHk6InLhBkao3({p59p z&8RajEK)~A)pPO2{=9oel1`vqqt1(IbpG;@w1JN2@cwKyF1yxC9&`NLuLXf%Fvs-Y zVAv4+_0vXz70=5mfk3lzh+*?-xN=1p24=FnYBkq>~(U`w7FYpp& zljAp!Y4$qIAKF=>7sVj<@aPd%;FSnj-r&rb9z4#nuas_>z%?RfBD+40ISaI%(Fha`iUYSm*)x!#< z4k}pq)zux;Ht>&xm$+9gc>?ZfN8 z+^*wo(=Vt#M?aewIz-xihQc$`8ke>4u-_5=FDL!b#us#KbFE^% zR%I$_tO#Zypp0m}N7nQJkpa>&9$rsAGO@6Q;`DDtQ(N00S-ukWB*eX7S@oA~oN>5e|Vp{X>NnnMp!xBaqr`GW-?G=>b|t;?JozdDGu)#ICyP3$$YdE=Wj&%}oyAW4C8R`I6q=Y=n1+kmi@q8B%c(LLW(txW3 zy3)`$HeUeXx_I-kqgnV)aQt@T2CK}g60=tP$&>|GV`wBX?bmp0+FxIBtI9`K-u1k{ zw>YEQII=85>DKgmt^*3zfDA#(xQ-9bUdN)q&ninfZE&K^RmP{G&7$#ye8+Y(^WSyEv^{I`U&%py~uLHHCdy8C~3{2!ZjfAEio#%&MYrdf2;p z?L_5Q34AjGLN!xvSmm*47vb36N5qco>Z9wcYD=im0A6Gv#yV_^fkueiOd`^&TGK#6 z)zu24$$F0KK5fD;f;%?XcNKIs`n%WX)bYB3csBMIRCv|P*?%(egbPzVxtRemO2M+R zsD1=Rkw$0Lk|T}DifR1@aZo}&`NS`Ox|jyJv5xZy(WAi;^w+vNJBjzUx=vNKP zOH~(+)Y__>wVg5%NX{&e>&JKmHw@yc-KPZ;D*lsJQ!1y8wgm@H*U)_LQJmqI!de|F zdnC*bT|)Fqo*gMU!_-EYXNB>PcAxAN=^vMFHr=iu=+4N5S_P{4Jz?TTEV)i#Osy_97XbU062p>0SL!S$FUbLbk3~1~=?l2S>TG-__u>7w?{za@ zph}Q-i4xx##S0`__(x?Bh@1mFqg8PpcnWADd&oLplwvbRs6j#d!uLmaA0 zFVnS{3&Lw}^>qv!r}Z(zg=h=;JOr6*y?u0=Yjv6i>6HtV#Q*>(Lbd|||6IEoLmt=+ zMZnkLxY2HE+lz#&Zx}j>6>Z!bJ{F4D#4nT&`L;`qMi->Rr*W=}7R0eLAYiaicN-u&n4( zrJ!uPoLJIdD?8xr8qS>k>7dC+Fx|1H4Fu&!+---4GLcO20j4wMna&qDrjPjf*Vz7( z$Q#D?)@-%j?U_S`U00xEZOVq zdkZk+6j9b_+rgB_rR;{_gFmvt#ORH|7j`|peMS$JsmWjYyWD)y^HnhI0}77E_V(^5 zYhVA0Dfi!O^ApO+vFO0g!t?_IiXN`K2-mw>>azb_6%{?O+v$dAq2fO&N-;d&i?Y%M z%1^xF@-ucLYQH?qme0GKSS9Uyu0SF^WcOw*scz@i0vi9A!&)Ad`I@s}XSgr5!LuXK z!;<}h`2e%6ylYNr!L^OX$7lp?T5W6My=WN>V}J|zA# zrb^gSwmx)o`B5wysOca@Wz8;CpS=0E;e6w$VX?5$QJZPbu|_kq&sK(I9=*5+oa^Hu zgi^WGTF>W?8nMP0XImw1V~OrBsC~X6(6{$2o8>9a5|87y1b*UZuibU3C^Pc~0JsSV zpGLV7n6B$RP33_SW@=Oz9Phy1XwEJ~(wWU$OCgIuMD?jFlL!8PsB~*w+apt+9E7F5 zsCejlqPp*#cq9CF&w(#5Uu&&-o z-w_XNnUpxjG&}A`!3NLyKig&x(?4Fb;I1PTZ{B!eIDL~?j2$7``gBCn`PZo*Pg?kz z4?Y@MZ?B&&?`=%&D>16nzS!e6;Z=Nagp~J%cy&tHbA{gug$+n?pK&U6X!y(G^?PB) zPb~(w^vRa!f5W)FCk-PCPzLuXB6VA14R)wr8Yo4@?V`e^>?do9#8tGmU0FhR`D3pgYJ3Kw$)Bqh`mNV; zuMzm!=ZE9cltIJo|Ms=YcR2oq5~;*?_zrKfZe9<4drO-YG^M7SLuP;CC%r9skMbt* z05iTN7#zE6pt{bRu+GPWVeCoYTQ$_??5yl^?k(O^)RA6YoCxU+<{quP{!-tjoC2+gn;dig zTgT+}*g!tqvd?5ktwHD!>#*j~nRzFqskk|S+dwUP4T6fdo_mGhG7TPCr5brv@>Du7 za|;PK>Ws`ST5<+aS%RmkPpIC;>G$fY5v?L z=VgPdRWjcaEy5DFq#l2|V{&_I63N5&!c$qVX&%nga{H|1Emdzh&bPU#agLUa9f6lS z%zF#38^?K;$$EciGzBn~wA6If+;CmGewRL2b8@DS$&!(9APK+Cj?Vrl>G>(_NOcJ_ z7{!8QYJ1MJ-|=_a>vgR6_`lNi#i)j)@_T!K;2fg-*RZy%G@9Z{I3Vk4TugZR6nXe$ zm%Qv-f(P&U&|(vk#wm5IO3it**cVsiIYhBUaY6=TOYIe@x=e&T>h0`K2F+!Src#XJ zXwHqbIhBWl=3fKE6WY) z9Bkg;rrfA-;q$+f#vhf3Uq9oWI$jp7R6G>xGsYZQ(RW^DQB5D`C(x5#m8hi3?wrc9 zWc)QQ7WnvEOtSu*ck2U0A~8zvlSk1GA5A}-e432h+o^j72DN5+7&Vg)OWeu4STcmq zYQ)+eZ4Vcl5hrx4h*SO~N!r`o-=4t`olwedLV)j5uaGo)n*5eN!6>XSqG>pDHP!TT zXEbcQGrKt*>!Ae>Uq<^A!*VBngy&PnKr?hIz)qA;UoIRI97-KKiYiDJ6(D@MzmsfsXir%YY?9b2NE4bPU=4wOg~sx`zCUo z5~y8nXNaKl1nB>tyZI=)evIm7qxJ|@jP?UsXksY# z>EZPWY4j~xlu)?oSmJs*QiW&lYaE)O6!GFB8+h(L3bS_Z)s{3Im?bQ+Awe%Q)g6J5 z)260M?=Dj6GII>4zow-`x}0Ennzy_zM1=dcv~cH~olI+eY6%r4Y=RpP-6b<0f22Gn zuvXQ>f5cW?`9mJdx!G9RD!2 zCyfECYl^wMO|zQ{iE{PZ#vmFFvD1`fN-MlH|78tEy}O0-O<`V zM{8ph6=nPpNryilOtZjuKa2I(OOzy-^{T9L=zw29J>_n<>&eN(ufv>t&sb`?vnjzn zZ%hr>qI3$fl^IJq&CD1(cdq}%u;9e0=9(Hq4)cPk3vczF2yVFv;e?ihLGcxPndvOe z8m5K8#Fc63XU*Kxv0C{ZJ!7OI!tVIvPGyKrK9$J>)lKyZG1ztH<;FeK{(cju7 zMF#VT6T5?>hp^A2iYFH$@DYNGt6o+oD`PTiYfw@V)cQ}+;Qe$m*Lf7tav$yKbXm2H zEM1EOY^3ruKhP~ZZfyK8{C6p(-3~jm_KCO~iW19W3%&Yxv(kPKWn-C_{Za1zN}O|r zGZYU1K{;*UBurm&^>t*K@3uG{C6WP%JYw_q;l!iA{+lG=9F>Cg~>A2U~5Nl@BE{QCE8IoM<(Ef-4MFR*? zRPrM;o)O!^zi%j~vbSJDcOXpn*)L$w!Xbx#Mq~VTs5#M0okO(1tE<&(qM#*%BKg(K zH03fxMmC%bRPq6j9oh_DE^bvh1>v%Z@vi?p#j59O(IVK4_RbksCSQ$-*U%DO@-Z75 zoFrN#lv+{aSXbbkq7b-i8(l4$5c1kbN|jTDUNwJPej<6Cck%_twZn?maFEL~Y|NhS zg^iL)=pNwBtufXI!3fHTeiNbNV@awFy8ax`F?B%UvJDB*h61pdwL7gSBgTFiaL7lE zdz<@N+j%BnRzb)w^d3939E&X+7lND3DV`Q`8DpKFkgw7 zk0%}9AF|MGHn8`IOR-lfLHgsa)IJW)gG6V^{QL2nkP!3~06eFd;h`q7`&eU?s{cjx0e}QOl>X3P^x^n*pk`@6o7)LesKatZ zs)TJUK{Yf|0ys!Z3ode-75yZBxV6K-h0uCYv$pYFf+1EXWSQlAuc~TB{A5WeHXnVh zO4`qj#T89YR*VOiT%e27^7bRp;I6=FCW)H!VpnaqV`2D*HT`mm%Jr#H=-L>|ET8>4 z(vO+ai9R%`q~^9(l8ojEEqF{Jys^W5N@^Sh_Y#hur61){ILakg&lve#l10&PPpxEs z&$B36G>^qJA2}D_vv#OoYWGf9GsYh&WG&qBo$a0567v)YKdOY;l9r40n-^BPgr zpRu8`|r-8raN2raKyrn)IB*@zh8;Ihgb2xoh7v(E>+KqHql zH^z+=6qW)gn^x05-Hx^`_H@|6zXst)d9oxYV4dB;KfZaFpC4*R^8n#SQZEw3*~eNb zYzk-9zV}t;o!bGU92I0LuQ;(Y|8ew`63ky~h@PJ|W(40=lFQ1An=)6SI{KoLa0roYh>DCseLE zM9Wt1oN)T*IJ3??tw!F%=~_G5;232ni^2DDUXsBJ zs;&;V(m7(&W1y_NNO!SvqPU$V@Xug{MoLnz`39K_DOL5V8f_J#_CEhSp3SVDTodLJ zLe6_Q#XcCE&Z0jFuS-9GB1AgMEF_}E$(HcXOHg4H2<$+AN60PY;vkp(&Yd1$n4y*+ zAseW5{LYB(t?k1TSnOvvKu5%ta{$t#*-otQ{e_W8<+gRrtH=m<=-nC>zBPnTY1N-pGy{B{|BZKbv=yS zbP~DqJXoKYt8PRPkFHpN9GIUtPD~j6tIiru(a(%~FVceCRsP&Q^`be(E?7n3ZTb)v8%V$qZQ19r8oK4dD+n&NF>Lng;xgqpa%nWJl_s z&?rqZ2V-JQhuZ^Vf_v7eR$D!vll-ie$ml)Q(yaq&RHf>1K$UPu5ATD7l_4lcC)crc zTW$rV9XehBjmXz}&d%&u&AJ9e`u^p^85^4|vgvVYf*JKeiGeot%Q%Vg0y4`%%^Yas z52w!G?)LM^_h`&UKKgx|=6v3Pyllt0EnQ^Zf6nUVvq;x)M5qr@yaOi8I_rzNBUZ(H z|911Rh$ndFxxp2AbamiK+YJElfg*-PPstAG8rqb-LbK7}@>f?MuOC>0P%2{pb53^) z?cV8hpPCoWZC+&0#c}qh9HQBN82`GoDLum(pkz;t(mXDbQGGQ#Z1r>&#n|NK@Xoz~ zE%${21eRMfzsuDBTtLJRlq^kE5BV!14?kYLI-rfPW9-1o_sN{flFA12t+O7U;#C=| zv~x){DM8usQuB9L5{07|&-2|`D0k4jqPO{$9^NTQ6WfntkzU?+FCjWdZ)a{x>-B29 zI$3(K%s}J@q~N&&+G8#I6u8Cdbyk-)r^5fXV*y0{Nh6sz-3#Z!YLK+D?v7nh$}-m0 zT5s<^cprCPH5_&BF?ty`6(NDU=u|9b==`Ge`FClC@nh|(QmpO$7=l_VYG zCTqDvI=jCMYoethZRdRapc(*_-&hq8Tai3$n3&J5%p+~vlZf3sGOO}gQGBp2>u-t~ z3+fkh_@_27t`LF(*kAH@A`v11c~EijxOiyIZ{!q4m^!{7J(#lI^W$NUvCL lR5iEWYO|4t9a9w!1qL1lW)-jt@VRuQRtZGL7*xvb{vV;Bl5zk5 literal 9966 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 0 { @@ -643,7 +644,7 @@ func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress util.Address) (*BlockTe // Sort transactions by subnetwork ID before building Merkle tree sort.Slice(blockTxns, func(i, j int) bool { - return blockTxns[i].MsgTx().SubNetworkID < blockTxns[j].MsgTx().SubNetworkID + return subnetworkid.Less(&blockTxns[i].MsgTx().SubNetworkID, &blockTxns[j].MsgTx().SubNetworkID) }) // Create a new block ready to be solved. diff --git a/mining/policy_test.go b/mining/policy_test.go index 338b3bfce..7469f21ab 100644 --- a/mining/policy_test.go +++ b/mining/policy_test.go @@ -140,7 +140,7 @@ func TestCalcPriority(t *testing.T) { utxoSet: newUTXOSet([]*wire.MsgTx{commonSourceTx1}, []int32{7}), nextHeight: 169, - want: 1.35e+10, + want: 1.125e+10, }, { name: "one height 100 input, prio tx height 169", @@ -148,7 +148,7 @@ func TestCalcPriority(t *testing.T) { utxoSet: newUTXOSet([]*wire.MsgTx{commonSourceTx1}, []int32{100}), nextHeight: 169, - want: 5.75e+09, + want: 4.791666666666667e+09, }, { name: "one height 7 input, prio tx height 100000", @@ -156,7 +156,7 @@ func TestCalcPriority(t *testing.T) { utxoSet: newUTXOSet([]*wire.MsgTx{commonSourceTx1}, []int32{7}), nextHeight: 100000, - want: 8.33275e+12, + want: 6.943958333333333e+12, }, { name: "one height 100 input, prio tx height 100000", @@ -164,7 +164,7 @@ func TestCalcPriority(t *testing.T) { utxoSet: newUTXOSet([]*wire.MsgTx{commonSourceTx1}, []int32{100}), nextHeight: 100000, - want: 8.325e+12, + want: 6.9375e+12, }, } diff --git a/server/rpc/rpcserver.go b/server/rpc/rpcserver.go index 98e1effb0..431c8feb5 100644 --- a/server/rpc/rpcserver.go +++ b/server/rpc/rpcserver.go @@ -889,7 +889,7 @@ func handleGenerate(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte } } - if config.MainConfig().SubNetwork != wire.SubNetworkSupportsAll { + if !config.MainConfig().SubNetwork.IsEqual(&wire.SubNetworkSupportsAll) { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInvalidRequest.Code, Message: "`generate` is not supported on partial nodes.", @@ -2230,7 +2230,7 @@ func handleGetGenerate(s *Server, cmd interface{}, closeChan <-chan struct{}) (i // handleGetHashesPerSec implements the getHashesPerSec command. func handleGetHashesPerSec(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { - if config.MainConfig().SubNetwork != wire.SubNetworkSupportsAll { + if !config.MainConfig().SubNetwork.IsEqual(&wire.SubNetworkSupportsAll) { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInvalidRequest.Code, Message: "`getHashesPerSec` is not supported on partial nodes.", @@ -2319,7 +2319,7 @@ func handleGetMempoolInfo(s *Server, cmd interface{}, closeChan <-chan struct{}) // handleGetMiningInfo implements the getMiningInfo command. We only return the // fields that are not related to wallet functionality. func handleGetMiningInfo(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { - if config.MainConfig().SubNetwork != wire.SubNetworkSupportsAll { + if !config.MainConfig().SubNetwork.IsEqual(&wire.SubNetworkSupportsAll) { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInvalidRequest.Code, Message: "`getMiningInfo` is not supported on partial nodes.", @@ -2381,7 +2381,7 @@ func handleGetNetTotals(s *Server, cmd interface{}, closeChan <-chan struct{}) ( // This command had been (possibly temporarily) dropped. // Originally it relied on height, which no longer makes sense. func handleGetNetworkHashPS(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { - if config.MainConfig().SubNetwork != wire.SubNetworkSupportsAll { + if !config.MainConfig().SubNetwork.IsEqual(&wire.SubNetworkSupportsAll) { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInvalidRequest.Code, Message: "`getNetworkHashPS` is not supported on partial nodes.", @@ -3286,7 +3286,7 @@ func handleSendRawTransaction(s *Server, cmd interface{}, closeChan <-chan struc // handleSetGenerate implements the setGenerate command. func handleSetGenerate(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { - if config.MainConfig().SubNetwork != wire.SubNetworkSupportsAll { + if !config.MainConfig().SubNetwork.IsEqual(&wire.SubNetworkSupportsAll) { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInvalidRequest.Code, Message: "`setGenerate` is not supported on partial nodes.", diff --git a/util/block_test.go b/util/block_test.go index 585ecf845..ee0d282fa 100644 --- a/util/block_test.go +++ b/util/block_test.go @@ -54,10 +54,10 @@ func TestBlock(t *testing.T) { // Hashes for the transactions in Block100000. wantTxHashes := []string{ - "4f2a5f1e00034ed3222e0e7fae8485ad3154d40b21b1c1b64ec74ce389a1bb1d", - "cdd164e1b3c910e1b54349d442d26541830d0551a15c8b2e202aa7f96ccf3b32", - "7fb0543009c39a12a0e5b3c23f157c9152f9e956412a825d296d1e3826dcf81c", - "ba611a9e39e784e51ea9efe66453de7a0355deae454f63c526a1938a58f683fc", + "171090dd8ab478a2c4499858abd5d9b10e173b659bab5d5acca68c7dcb4c519e", + "fc9100986f2a188ccffe206a4c013aaa0c7442898b2f58d474f0b4f534600e0b", + "42ef8bcc302b4a92d479c02c4bf6cb154f26ad9915433da7fb102f6fd135b5c3", + "c8eeef60be812de9982d066be027fee93f2c226c840670424a413fbd66ad36dd", } // Create a new block to nuke all cached data. @@ -146,10 +146,10 @@ func TestBlock(t *testing.T) { // Transaction offsets and length for the transaction in Block100000. wantTxLocs := []wire.TxLoc{ - {TxStart: 122, TxLen: 151}, - {TxStart: 273, TxLen: 275}, - {TxStart: 548, TxLen: 273}, - {TxStart: 821, TxLen: 241}, + {TxStart: 122, TxLen: 163}, + {TxStart: 285, TxLen: 287}, + {TxStart: 572, TxLen: 285}, + {TxStart: 857, TxLen: 253}, } // Ensure the transaction location information is accurate. diff --git a/util/bloom/filter_test.go b/util/bloom/filter_test.go index 59eaa15a9..ab7ea589c 100644 --- a/util/bloom/filter_test.go +++ b/util/bloom/filter_test.go @@ -255,7 +255,7 @@ func TestFilterBloomMatch(t *testing.T) { "3D11000000001976A91404943FDD508053C75000106D3BC6" + "E2754DBCFF1988AC2F15DE00000000001976A914A266436D" + "2965547608B9E15D9032A7B9D64FA43188AC000000000000" + - "00000100000000000000" + "00000100000000000000000000000000000000000000" strBytes, err := hex.DecodeString(str) if err != nil { t.Errorf("TestFilterBloomMatch DecodeString failure: %v", err) @@ -266,18 +266,24 @@ func TestFilterBloomMatch(t *testing.T) { t.Errorf("TestFilterBloomMatch NewTxFromBytes failure: %v", err) return } - spendingTxStr := "0100000001F66914B25A46137FB0551E95CCE775254B8711" + - "D01D7D258C119396E57E105622000000008C493046022100" + - "DA0DC6AECEFE1E06EFDF05773757DEB168820930E3B0D03F" + - "46F5FCF150BF990C022100D25B5C87040076E4F253F8262E" + - "763E2DD51E7FF0BE157727C4BC42807F17BD39014104E6C2" + - "6EF67DC610D2CD192484789A6CF9AEA9930B944B7E2DB534" + - "2B9D9E5B9FF79AFF9A2EE1978DD7FD01DFC522EE02283D3B" + - "06A9D03ACF8096968D7DBB0F9178FFFFFFFFFFFFFFFF028B" + - "A7940E000000001976A914BADEECFDEF0507247FC8F74241" + - "D73BC039972D7B88AC4094A802000000001976A914C10932" + - "483FEC93ED51F5FE95E72559F2CC7043F988AC0000000000" + - "0000000100000000000000" + spendingTxStr := "0100000001D25EE298643F1793383A12" + + "8F8E70FF33932B6532511CC6E7556D03" + + "3370AB7CB7000000008C493046022100" + + "DA0DC6AECEFE1E06EFDF05773757DEB1" + + "68820930E3B0D03F46F5FCF150BF990C" + + "022100D25B5C87040076E4F253F8262E" + + "763E2DD51E7FF0BE157727C4BC42807F" + + "17BD39014104E6C26EF67DC610D2CD19" + + "2484789A6CF9AEA9930B944B7E2DB534" + + "2B9D9E5B9FF79AFF9A2EE1978DD7FD01" + + "DFC522EE02283D3B06A9D03ACF809696" + + "8D7DBB0F9178FFFFFFFFFFFFFFFF028B" + + "A7940E000000001976A914BADEECFDEF" + + "0507247FC8F74241D73BC039972D7B88" + + "AC4094A802000000001976A914C10932" + + "483FEC93ED51F5FE95E72559F2CC7043" + + "F988AC00000000000000000100000000" + + "000000000000000000000000000000" spendingTxBytes, err := hex.DecodeString(spendingTxStr) if err != nil { t.Errorf("TestFilterBloomMatch DecodeString failed to decode spendingTxStr: %v", err) @@ -291,7 +297,7 @@ func TestFilterBloomMatch(t *testing.T) { } f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) - inputStr := "2256107ee59693118c257d1dd011874b2575e7cc951e55b07f13465ab21469f6" // byte-reversed tx hash + inputStr := "b77cab7033036d55e7c61c5132652b9333ff708e8f123a3893173f6498e25ed2" // byte-reversed tx hash hash, err := daghash.NewHashFromStr(inputStr) if err != nil { t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err) @@ -303,7 +309,7 @@ func TestFilterBloomMatch(t *testing.T) { } f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) - inputStr = "f66914b25a46137fb0551e95cce775254b8711d01d7d258c119396e57e105622" // non-reversed tx hash + inputStr = "d25ee298643f1793383a128f8e70ff33932b6532511cc6e7556d033370ab7cb7" // non-reversed tx hash hashBytes, err := hex.DecodeString(inputStr) if err != nil { t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err) @@ -511,7 +517,8 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { 0xE0, 0xD8, 0x11, 0x13, 0xC3, 0x80, 0x74, 0x20, 0xCE, 0x13, 0xAD, 0x13, 0x57, 0x23, 0x1A, 0x22, 0x52, 0x24, 0x7D, 0x97, 0xA4, 0x6A, 0x91, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xBC, 0xAD, 0x20, 0xA6, 0xA2, 0x98, // Txs[1] 0x27, 0xD1, 0x42, 0x4F, 0x08, 0x98, 0x92, 0x55, 0x12, 0x0B, 0xF7, @@ -531,7 +538,8 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { 0x00, 0x19, 0x76, 0xA9, 0x14, 0x1B, 0x8D, 0xD1, 0x3B, 0x99, 0x4B, 0xCF, 0xC7, 0x87, 0xB3, 0x2A, 0xEA, 0xDF, 0x58, 0xCC, 0xB3, 0x61, 0x5C, 0xBD, 0x54, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0xFD, 0xAC, 0xF9, 0xB3, 0xEB, 0x07, // Txs[2] 0x74, 0x12, 0xE7, 0xA9, 0x68, 0xD2, 0xE4, 0xF1, 0x1B, 0x9A, 0x9D, 0xEE, 0x31, 0x2D, 0x66, 0x61, 0x87, 0xED, 0x77, 0xEE, 0x7D, 0x26, @@ -575,7 +583,8 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { 0xB5, 0x51, 0x41, 0xD0, 0x97, 0xEA, 0x5D, 0xF7, 0xA0, 0xED, 0x33, 0x0C, 0xF7, 0x94, 0x37, 0x6E, 0x53, 0xEC, 0x8D, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x5B, 0xF0, 0xE2, 0x14, 0xAA, 0x40, // Txs[3] 0x69, 0xA3, 0xE7, 0x92, 0xEC, 0xEE, 0x1E, 0x1B, 0xF0, 0xC1, 0xD3, 0x97, 0xCD, 0xE8, 0xDD, 0x08, 0x13, 0x8F, 0x4B, 0x72, 0xA0, 0x06, @@ -648,7 +657,8 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { 0xEF, 0xD8, 0x0D, 0x99, 0x17, 0x9F, 0x4F, 0x4F, 0xF6, 0xF4, 0xDD, 0x0A, 0x00, 0x7D, 0x01, 0x8C, 0x38, 0x5D, 0x21, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x83, 0x45, 0x37, 0xB2, 0xF1, 0xCE, // Txs[4] 0x8E, 0xF9, 0x37, 0x3A, 0x25, 0x8E, 0x10, 0x54, 0x5C, 0xE5, 0xA5, 0x0B, 0x75, 0x8D, 0xF6, 0x16, 0xCD, 0x43, 0x56, 0xE0, 0x03, 0x25, @@ -673,7 +683,8 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { 0x00, 0x19, 0x76, 0xA9, 0x14, 0xA8, 0x4E, 0x27, 0x29, 0x33, 0xAA, 0xF8, 0x7E, 0x17, 0x15, 0xD7, 0x78, 0x6C, 0x51, 0xDF, 0xAE, 0xB5, 0xB6, 0x5A, 0x6F, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x43, 0xAC, 0x81, 0xC8, 0xE6, 0xF6, // Txs[5] 0xEF, 0x30, 0x7D, 0xFE, 0x17, 0xF3, 0xD9, 0x06, 0xD9, 0x99, 0xE2, 0x3E, 0x01, 0x89, 0xFD, 0xA8, 0x38, 0xC5, 0x51, 0x0D, 0x85, 0x09, @@ -699,6 +710,8 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { 0x00, 0xD7, 0x96, 0x8B, 0x34, 0x05, 0xC0, 0x34, 0xAD, 0xC3, 0x8D, 0x4D, 0x8F, 0xB9, 0xBD, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x48, 0xCC, 0x91, 0x75, 0x01, 0xEA, // Txs[6] 0x5C, 0x55, 0xF4, 0xA8, 0xD2, 0x00, 0x9C, 0x05, 0x67, 0xC4, 0x0C, 0xFE, 0x03, 0x7C, 0x2E, 0x71, 0xAF, 0x01, 0x7D, 0x0A, 0x45, 0x2F, @@ -738,7 +751,8 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { 0x82, 0x2F, 0x1A, 0xD5, 0x80, 0xB0, 0x43, 0xC7, 0xB3, 0xDF, 0x2E, 0x40, 0x0F, 0x86, 0x99, 0xEB, 0x48, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, } block, err := util.NewBlockFromBytes(blockBytes) if err != nil { @@ -772,7 +786,7 @@ func TestFilterInsertP2PubKeyOnly(t *testing.T) { _, _ = bloom.NewMerkleBlock(block, f) // We should match the generation pubkey - inputStr = "807014abe7988704c8097b6ea882489cb1dc54daff96947eab9f6c04f2271252" //1st tx hash + inputStr = "042aaac8c54b07f1e729e01d38b1fb26c6d595ed5920b856faf4070db79ce933" //0st tx hash hash, err := daghash.NewHashFromStr(inputStr) if err != nil { t.Errorf("TestMerkleBlockP2PubKeyOnly NewHashFromStr failed: %v", err) diff --git a/util/bloom/merkleblock_test.go b/util/bloom/merkleblock_test.go index a2626917e..dcb8d3a7f 100644 --- a/util/bloom/merkleblock_test.go +++ b/util/bloom/merkleblock_test.go @@ -42,7 +42,8 @@ func TestMerkleBlock3(t *testing.T) { 0x4C, 0x74, 0xFB, 0xCC, 0xFD, 0x4F, 0x49, 0x63, 0x9C, 0xF1, 0xBD, 0xC9, 0x4A, 0x56, 0x72, 0xBB, 0x15, 0xAD, 0x5D, 0x4C, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, } blk, err := util.NewBlockFromBytes(blockBytes) @@ -65,22 +66,22 @@ func TestMerkleBlock3(t *testing.T) { mBlock, _ := bloom.NewMerkleBlock(blk, f) want := []byte{ - 0x01, 0x00, 0x00, 0x00, 0x01, 0x79, 0xcd, 0xa8, - 0x56, 0xb1, 0x43, 0xd9, 0xdb, 0x2c, 0x1c, 0xaf, - 0xf0, 0x1d, 0x1a, 0xec, 0xc8, 0x63, 0x0d, 0x30, - 0x62, 0x5d, 0x10, 0xe8, 0xb4, 0xb8, 0xb0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x0c, 0xc0, - 0x69, 0xd6, 0xa3, 0xe3, 0x3e, 0x3f, 0xf8, 0x4a, - 0x5c, 0x41, 0xd9, 0xd3, 0xfe, 0xbe, 0x7c, 0x77, - 0x0f, 0xdc, 0xc9, 0x6b, 0x2c, 0x3f, 0xf6, 0x0a, - 0xbe, 0x18, 0x4f, 0x19, 0x63, 0x67, 0x29, 0x1b, - 0x4d, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x86, 0x04, - 0x1b, 0x8f, 0xa4, 0x5d, 0x63, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xaa, 0xda, - 0x38, 0x18, 0x2c, 0x17, 0xd8, 0x41, 0x3b, 0xd2, - 0xba, 0xd3, 0x16, 0x26, 0xb0, 0x96, 0x84, 0x6f, - 0x6b, 0xd4, 0xc4, 0xd3, 0xa6, 0x64, 0x45, 0x78, - 0x62, 0x5a, 0x23, 0xd4, 0x69, 0x92, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x79, 0xCD, 0xA8, + 0x56, 0xB1, 0x43, 0xD9, 0xDB, 0x2C, 0x1C, 0xAF, + 0xF0, 0x1D, 0x1A, 0xEC, 0xC8, 0x63, 0x0D, 0x30, + 0x62, 0x5D, 0x10, 0xE8, 0xB4, 0xB8, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x0C, 0xC0, + 0x69, 0xD6, 0xA3, 0xE3, 0x3E, 0x3F, 0xF8, 0x4A, + 0x5C, 0x41, 0xD9, 0xD3, 0xFE, 0xBE, 0x7C, 0x77, + 0x0F, 0xDC, 0xC9, 0x6B, 0x2C, 0x3F, 0xF6, 0x0A, + 0xBE, 0x18, 0x4F, 0x19, 0x63, 0x67, 0x29, 0x1B, + 0x4D, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x86, 0x04, + 0x1B, 0x8F, 0xA4, 0x5D, 0x63, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0xB0, + 0x08, 0x73, 0xD7, 0xDE, 0x86, 0xF3, 0x9E, 0x37, + 0x06, 0x03, 0xB4, 0x75, 0xB4, 0xAC, 0xB4, 0x67, + 0xD3, 0x98, 0x3D, 0x2B, 0x9E, 0xE5, 0x35, 0x83, + 0x1A, 0xA4, 0xEC, 0xD5, 0x76, 0x18, 0x01, 0x00, } t.Log(spew.Sdump(want)) if err != nil { diff --git a/util/coinset/coins_test.go b/util/coinset/coins_test.go index ba1fdb8fd..a61aaf9b2 100644 --- a/util/coinset/coins_test.go +++ b/util/coinset/coins_test.go @@ -223,7 +223,7 @@ func TestMinPrioritySelector(t *testing.T) { var ( // should be two outpoints, with 1st one having 0.035BTC value. testSimpleCoinNumConfs = int64(1) - testSimpleCoinTxHash = "df280b66ce73fbd3713fe280e24bfa8bb21a7ccdfc81829d48bf1e16f8226310" + testSimpleCoinTxHash = "8b6cefebd8a9b3ec28e9195b852edc306bc7d6b582bd5c8b74b602bbed4124b8" testSimpleCoinTxHex = "0100000001A214A110F79E4ABE073865EA5B3745C6E82C91" + "3BAD44BE70652804A5E4003B0A010000008C493046022100" + "EDD18A69664EFA57264BE207100C203E6CADE1888CBB88A0" + @@ -235,7 +235,7 @@ var ( "673500000000001976A914686DD149A79B4A559D561FBC39" + "6D3E3C6628B98D88ACE86EF102000000001976A914AC3F99" + "5655E81B875B38B64351D6F896DDBFC68588AC0000000000" + - "000000010000000000000000" + "000000010000000000000000000000000000000000000000" testSimpleCoinTxValue0 = util.Amount(3500000) testSimpleCoinTxValueAge0 = int64(testSimpleCoinTxValue0) * testSimpleCoinNumConfs testSimpleCoinTxPkScript0Hex = "76a914686dd149a79b4a559d561fbc396d3e3c6628b98d88ac" diff --git a/util/subnetworkid/subnetworkid.go b/util/subnetworkid/subnetworkid.go new file mode 100644 index 000000000..16ff4f201 --- /dev/null +++ b/util/subnetworkid/subnetworkid.go @@ -0,0 +1,198 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2015 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package subnetworkid + +import ( + "encoding/hex" + "fmt" + "math/big" + "sort" + "strings" +) + +// IDLength of array used to store the sub-network ID. See SubNetworkID. +const IDLength = 20 + +// MaxStringSize is the maximum length of a SubNetworkID string. +const MaxStringSize = IDLength * 2 + +// ErrIDStrSize describes an error that indicates the caller specified an ID +// string that has too many characters. +var ErrIDStrSize = fmt.Errorf("max ID string length is %v bytes", MaxStringSize) + +// SubNetworkID is used in several of the bitcoin messages and common structures. It +// typically represents ripmed160(sha256(data)). +type SubNetworkID [IDLength]byte + +// String returns the SubNetworkID as the hexadecimal string of the byte-reversed +// hash. +func (id SubNetworkID) String() string { + for i := 0; i < IDLength/2; i++ { + id[i], id[IDLength-1-i] = id[IDLength-1-i], id[i] + } + return hex.EncodeToString(id[:]) +} + +// Strings returns a slice of strings representing the IDs in the given slice of IDs +func Strings(ids []SubNetworkID) []string { + strings := make([]string, len(ids)) + for i, id := range ids { + strings[i] = id.String() + } + + return strings +} + +// CloneBytes returns a copy of the bytes which represent the ID as a byte +// slice. +// +// NOTE: It is generally cheaper to just slice the ID directly thereby reusing +// the same bytes rather than calling this method. +func (id *SubNetworkID) CloneBytes() []byte { + newID := make([]byte, IDLength) + copy(newID, id[:]) + + return newID +} + +// SetBytes sets the bytes which represent the ID. An error is returned if +// the number of bytes passed in is not IDLength. +func (id *SubNetworkID) SetBytes(newID []byte) error { + nhlen := len(newID) + if nhlen != IDLength { + return fmt.Errorf("invalid ID length of %v, want %v", nhlen, + IDLength) + } + copy(id[:], newID) + + return nil +} + +// IsEqual returns true if target is the same as ID. +func (id *SubNetworkID) IsEqual(target *SubNetworkID) bool { + if id == nil && target == nil { + return true + } + if id == nil || target == nil { + return false + } + return *id == *target +} + +// AreEqual returns true if both slices contain the same IDs. +// Either slice must not contain duplicates. +func AreEqual(first []SubNetworkID, second []SubNetworkID) bool { + if len(first) != len(second) { + return false + } + + for i := range first { + if first[i] != second[i] { + return false + } + } + + return true +} + +// New returns a new ID from a byte slice. An error is returned if +// the number of bytes passed in is not IDLength. +func New(newID []byte) (*SubNetworkID, error) { + var sh SubNetworkID + err := sh.SetBytes(newID) + if err != nil { + return nil, err + } + return &sh, err +} + +// NewFromStr creates a SubNetworkID from a string. The string should be +// the hexadecimal string of a byte-reversed hash, but any missing characters +// result in zero padding at the end of the SubNetworkID. +func NewFromStr(id string) (*SubNetworkID, error) { + ret := new(SubNetworkID) + err := Decode(ret, id) + if err != nil { + return nil, err + } + return ret, nil +} + +// Decode decodes the byte-reversed hexadecimal string encoding of a SubNetworkID to a +// destination. +func Decode(dst *SubNetworkID, src string) error { + // Return error if ID string is too long. + if len(src) > MaxStringSize { + return ErrIDStrSize + } + + // Hex decoder expects the ID to be a multiple of two. When not, pad + // with a leading zero. + var srcBytes []byte + if len(src)%2 == 0 { + srcBytes = []byte(src) + } else { + srcBytes = make([]byte, 1+len(src)) + srcBytes[0] = '0' + copy(srcBytes[1:], src) + } + + // Hex decode the source bytes to a temporary destination. + var reversedHash SubNetworkID + _, err := hex.Decode(reversedHash[IDLength-hex.DecodedLen(len(srcBytes)):], srcBytes) + if err != nil { + return err + } + + // Reverse copy from the temporary hash to destination. Because the + // temporary was zeroed, the written result will be correctly padded. + for i, b := range reversedHash[:IDLength/2] { + dst[i], dst[IDLength-1-i] = reversedHash[IDLength-1-i], b + } + + return nil +} + +// ToBig converts a SubNetworkID into a big.Int that can be used to +// perform math comparisons. +func ToBig(id *SubNetworkID) *big.Int { + // A Hash is in little-endian, but the big package wants the bytes in + // big-endian, so reverse them. + buf := *id + blen := len(buf) + for i := 0; i < blen/2; i++ { + buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i] + } + + return new(big.Int).SetBytes(buf[:]) +} + +// Cmp compares id and target and returns: +// +// -1 if id < target +// 0 if id == target +// +1 if id > target +// +func (id *SubNetworkID) Cmp(target *SubNetworkID) int { + return ToBig(id).Cmp(ToBig(target)) +} + +// Less returns true iff id a is less than id b +func Less(a *SubNetworkID, b *SubNetworkID) bool { + return a.Cmp(b) < 0 +} + +// JoinIDsStrings joins all the stringified IDs separated by a separator +func JoinIDsStrings(ids []SubNetworkID, separator string) string { + return strings.Join(Strings(ids), separator) +} + +// Sort sorts a slice of ids +func Sort(ids []SubNetworkID) { + sort.Slice(ids, func(i, j int) bool { + return Less(&ids[i], &ids[j]) + }) +} diff --git a/util/tx_test.go b/util/tx_test.go index 28059583f..05b84a501 100644 --- a/util/tx_test.go +++ b/util/tx_test.go @@ -35,7 +35,7 @@ func TestTx(t *testing.T) { } // Hash for block 100,000 transaction 0. - wantHashStr := "4f2a5f1e00034ed3222e0e7fae8485ad3154d40b21b1c1b64ec74ce389a1bb1d" + wantHashStr := "171090dd8ab478a2c4499858abd5d9b10e173b659bab5d5acca68c7dcb4c519e" wantHash, err := daghash.NewHashFromStr(wantHashStr) if err != nil { t.Errorf("NewHashFromStr: %v", err) diff --git a/util/txsort/testdata/bip69-1.hex b/util/txsort/testdata/bip69-1.hex index 005394b14..a174d71e5 100644 --- a/util/txsort/testdata/bip69-1.hex +++ b/util/txsort/testdata/bip69-1.hex @@ -1 +1 @@ -0100000011AAD553BB1650007E9982A8AC79D227CD8C831E1573B11F25573A37664E5F3E64000000006A47304402205438CEDD30EE828B0938A863E08D810526123746C1F4ABEE5B7BC2312373450C02207F26914F4275F8F0040AB3375BACC8C5D610C095DB8ED0785DE5DC57456591A601210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFC26F3EB7932F7ACDDC5DDD26602B77E7516079B03090A16E2C2F5485D1FDE028000000006B483045022100F81D98C1DE9BB61063A5E6671D191B400FDA3A07D886E663799760393405439D0220234303C9AF4BAD3D665F00277FE70CDD26CD56679F114A40D9107249D29C979401210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF456A9E597129F5DF2E11B842833FC19A94C563F57449281D3CD01249A830A1F0000000006A47304402202310B00924794EF68A8F09564FD0BB128838C66BC45D1A3F95C5CAB52680F166022039FC99138C29F6C434012B14ACA651B1C02D97324D6BD9DD0FFCED0782C7E3BD01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF571FB3E02278217852DD5D299947E2B7354A639ADC32EC1FA7B82CFB5DEC530E000000006B483045022100D276251F1F4479D8521269EC8B1B45C6F0E779FCF1658EC627689FA8A55A9CA50220212A1E307E6182479818C543E1B47D62E4FC3CE6CC7FC78183C7071D245839DF01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF5D8DE50362FF33D3526AC3602E9EE25C1A349DEF086A7FC1D9941AAEB9E91D38010000006B4830450221008768EEB1240451C127B88D89047DD387D13357CE5496726FC7813EDC6ACD55AC022015187451C3FB66629AF38FDB061DFB39899244B15C45E4A7CCC31064A059730D01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF60AD3408B89EA19CAF3ABD5E74E7A084344987C64B1563AF52242E9D2A8320F3000000006B4830450221009BE4261EC050EBF33FA3D47248C7086E4C247CAFBB100EA7CEE4AA81CD1383F5022008A70D6402B153560096C849D7DA6FE61C771A60E41FF457AAC30673CECEAFEE01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFE9B483A8AC4129780C88D1BABE41E89DC10A26DEDBF14F80A28474E9A11104DE010000006B4830450221009BC40EEE321B39B5DC26883F79CD1F5A226FC6EED9E79E21D828F4C23190C57E022078182FD6086E265589105023D9EFA4CBA83F38C674A499481BD54EEE196B033F01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFE28DB9462D3004E21E765E03A45ECB147F136A20BA8BCA78BA60EBFC8E2F8B3B000000006A47304402200FB572B7C6916515452E370C2B6F97FCAE54ABE0793D804A5A53E419983FAE1602205191984B6928BF4A1E25B00E5B5569A0CE1ECB82DB2DEA75FE4378673B53B9E801210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF7A1EF65FF1B7B7740C662AB6C9735ACE4A16279C23A1DB5709ED652918FFFF54010000006A47304402206BC218A925F7280D615C8EA4F0131A9F26E7FC64CFF6EEEB44EDB88ABA14F1910220779D5D67231BC2D2D93C3C5AB74DCD193DD3D04023E58709AD7FFBF95161BE6201210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF850CECF958468CA7FFA6A490AFE13B8C271B1326B0DDC1FDFDF9F3C7E365FDBA000000006A473044022047DF98CC26BD2BFDC5B2B97C27AEAD78A214810FF023E721339292D5CE50823D02205FE99DC5F667908974DAE40CC7A9475AF7FA6671BA44F64A00FCD01FA12AB523012102CA46FA75454650AFBA1784BC7B079D687E808634411E4BEFF1F70E44596308A1FFFFFFFFFFFFFFFF8640E312040E476CF6727C60CA3F4A3AD51623500AACDDA96E7728DBDD99E8A5000000006A47304402205566AA84D3D84226D5AB93E6F253B57B3EF37EB09BB73441DAE35DE86271352A02206EE0B7F800F73695A2073A2967C9AD99E19F6DDF18CE877ADF822E408BA9291E01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF91C1889C5C24B93B56E643121F7A05A34C10C5495C450504C7B5AFCB37E11D7A000000006B483045022100DF61D45BBAA4571CDD6C5C822CBA458CDC55285CDF7BA9CD5BB9FC18096DEB9102201CAF8C771204DF7FD7C920C4489DA7BC3A60E1D23C1A97E237C63AFE53250B4A01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF2470947216EB81EA0EEEB4FE19362EC05767DB01C3AA3006BB499E8B6D6EAA26010000006A473044022031501A0B2846B8822A32B9947B058D89D32FC758E009FC2130C2E5EFFC925AF70220574EF3C9E350CEF726C75114F0701FD8B188C6EC5F84ADCE0ED5C393828A5AE001210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF0ABCD77D65CC14363F8262898335F184D6DA5AD060FF9E40BF201741022C2B40010000006B483045022100A6AC110802B699F9A2BFF0EEA252D32E3D572B19214D49D8BB7405EFA2AF28F1022033B7563EB595F6D7ED7EC01734E17B505214FE0851352ED9C3C8120D53268E9A01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFA43BEBBEBF07452A893A95BFEA1D5DB338D23579BE172FE803DCE02EEB7C037D010000006B483045022100EBC77ED0F11D15FE630FE533DC350C2DDC1C81CFEB81D5A27D0587163F58A28C02200983B2A32A1014BAB633BFC9258083AC282B79566B6B3FA45C1E6758610444F401210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFB102113FA46CE949616D9CDA00F6B10231336B3928EAAAC6BFE42D1BF3561D6C010000006A473044022010F8731929A55C1C49610722E965635529ED895B2292D781B183D465799906B20220098359ADCBC669CD4B294CC129B110FE035D2F76517248F4B7129F3BF793D07F01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFB861FAB2CDE188499758346BE46B5FBEC635ADDFC4E7B0C8A07C0A908F2B11B4000000006A47304402207328142BB02EF5D6496A210300F4AEA71F67683B842FA3DF32CAE6C88B49A9BB022020F56DDFF5042260CFDA2C9F39B7DEC858CC2F4A76A987CD2DC25945B04E15FE01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF027064D817000000001976A9144A5FBA237213A062F6F57978F796390BDCF8D01588AC00902F50090000001976A9145BE32612930B8323ADD2212A4EC03C1562084F8488AC00000000000000000100000000000000 \ No newline at end of file +0100000011AAD553BB1650007E9982A8AC79D227CD8C831E1573B11F25573A37664E5F3E64000000006A47304402205438CEDD30EE828B0938A863E08D810526123746C1F4ABEE5B7BC2312373450C02207F26914F4275F8F0040AB3375BACC8C5D610C095DB8ED0785DE5DC57456591A601210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFC26F3EB7932F7ACDDC5DDD26602B77E7516079B03090A16E2C2F5485D1FDE028000000006B483045022100F81D98C1DE9BB61063A5E6671D191B400FDA3A07D886E663799760393405439D0220234303C9AF4BAD3D665F00277FE70CDD26CD56679F114A40D9107249D29C979401210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF456A9E597129F5DF2E11B842833FC19A94C563F57449281D3CD01249A830A1F0000000006A47304402202310B00924794EF68A8F09564FD0BB128838C66BC45D1A3F95C5CAB52680F166022039FC99138C29F6C434012B14ACA651B1C02D97324D6BD9DD0FFCED0782C7E3BD01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF571FB3E02278217852DD5D299947E2B7354A639ADC32EC1FA7B82CFB5DEC530E000000006B483045022100D276251F1F4479D8521269EC8B1B45C6F0E779FCF1658EC627689FA8A55A9CA50220212A1E307E6182479818C543E1B47D62E4FC3CE6CC7FC78183C7071D245839DF01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF5D8DE50362FF33D3526AC3602E9EE25C1A349DEF086A7FC1D9941AAEB9E91D38010000006B4830450221008768EEB1240451C127B88D89047DD387D13357CE5496726FC7813EDC6ACD55AC022015187451C3FB66629AF38FDB061DFB39899244B15C45E4A7CCC31064A059730D01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF60AD3408B89EA19CAF3ABD5E74E7A084344987C64B1563AF52242E9D2A8320F3000000006B4830450221009BE4261EC050EBF33FA3D47248C7086E4C247CAFBB100EA7CEE4AA81CD1383F5022008A70D6402B153560096C849D7DA6FE61C771A60E41FF457AAC30673CECEAFEE01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFE9B483A8AC4129780C88D1BABE41E89DC10A26DEDBF14F80A28474E9A11104DE010000006B4830450221009BC40EEE321B39B5DC26883F79CD1F5A226FC6EED9E79E21D828F4C23190C57E022078182FD6086E265589105023D9EFA4CBA83F38C674A499481BD54EEE196B033F01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFE28DB9462D3004E21E765E03A45ECB147F136A20BA8BCA78BA60EBFC8E2F8B3B000000006A47304402200FB572B7C6916515452E370C2B6F97FCAE54ABE0793D804A5A53E419983FAE1602205191984B6928BF4A1E25B00E5B5569A0CE1ECB82DB2DEA75FE4378673B53B9E801210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF7A1EF65FF1B7B7740C662AB6C9735ACE4A16279C23A1DB5709ED652918FFFF54010000006A47304402206BC218A925F7280D615C8EA4F0131A9F26E7FC64CFF6EEEB44EDB88ABA14F1910220779D5D67231BC2D2D93C3C5AB74DCD193DD3D04023E58709AD7FFBF95161BE6201210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF850CECF958468CA7FFA6A490AFE13B8C271B1326B0DDC1FDFDF9F3C7E365FDBA000000006A473044022047DF98CC26BD2BFDC5B2B97C27AEAD78A214810FF023E721339292D5CE50823D02205FE99DC5F667908974DAE40CC7A9475AF7FA6671BA44F64A00FCD01FA12AB523012102CA46FA75454650AFBA1784BC7B079D687E808634411E4BEFF1F70E44596308A1FFFFFFFFFFFFFFFF8640E312040E476CF6727C60CA3F4A3AD51623500AACDDA96E7728DBDD99E8A5000000006A47304402205566AA84D3D84226D5AB93E6F253B57B3EF37EB09BB73441DAE35DE86271352A02206EE0B7F800F73695A2073A2967C9AD99E19F6DDF18CE877ADF822E408BA9291E01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF91C1889C5C24B93B56E643121F7A05A34C10C5495C450504C7B5AFCB37E11D7A000000006B483045022100DF61D45BBAA4571CDD6C5C822CBA458CDC55285CDF7BA9CD5BB9FC18096DEB9102201CAF8C771204DF7FD7C920C4489DA7BC3A60E1D23C1A97E237C63AFE53250B4A01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF2470947216EB81EA0EEEB4FE19362EC05767DB01C3AA3006BB499E8B6D6EAA26010000006A473044022031501A0B2846B8822A32B9947B058D89D32FC758E009FC2130C2E5EFFC925AF70220574EF3C9E350CEF726C75114F0701FD8B188C6EC5F84ADCE0ED5C393828A5AE001210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF0ABCD77D65CC14363F8262898335F184D6DA5AD060FF9E40BF201741022C2B40010000006B483045022100A6AC110802B699F9A2BFF0EEA252D32E3D572B19214D49D8BB7405EFA2AF28F1022033B7563EB595F6D7ED7EC01734E17B505214FE0851352ED9C3C8120D53268E9A01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFA43BEBBEBF07452A893A95BFEA1D5DB338D23579BE172FE803DCE02EEB7C037D010000006B483045022100EBC77ED0F11D15FE630FE533DC350C2DDC1C81CFEB81D5A27D0587163F58A28C02200983B2A32A1014BAB633BFC9258083AC282B79566B6B3FA45C1E6758610444F401210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFB102113FA46CE949616D9CDA00F6B10231336B3928EAAAC6BFE42D1BF3561D6C010000006A473044022010F8731929A55C1C49610722E965635529ED895B2292D781B183D465799906B20220098359ADCBC669CD4B294CC129B110FE035D2F76517248F4B7129F3BF793D07F01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFFB861FAB2CDE188499758346BE46B5FBEC635ADDFC4E7B0C8A07C0A908F2B11B4000000006A47304402207328142BB02EF5D6496A210300F4AEA71F67683B842FA3DF32CAE6C88B49A9BB022020F56DDFF5042260CFDA2C9F39B7DEC858CC2F4A76A987CD2DC25945B04E15FE01210391064D5B2D1C70F264969046FCFF853A7E2BFDE5D121D38DC5EBD7BC37C2B210FFFFFFFFFFFFFFFF027064D817000000001976A9144A5FBA237213A062F6F57978F796390BDCF8D01588AC00902F50090000001976A9145BE32612930B8323ADD2212A4EC03C1562084F8488AC00000000000000000100000000000000000000000000000000000000 \ No newline at end of file diff --git a/util/txsort/testdata/bip69-2.hex b/util/txsort/testdata/bip69-2.hex index f3bfdac3d..515999887 100644 --- a/util/txsort/testdata/bip69-2.hex +++ b/util/txsort/testdata/bip69-2.hex @@ -1 +1 @@ -010000000255605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D28350000000049483045022100AA46504BAA86DF8A33B1192B1B9367B4D729DC41E389F2C04F3E5C7F0559AAE702205E82253A54BF5C4F65B7428551554B2045167D6D206DFE6A2E198127D3F7DF1501FFFFFFFFFFFFFFFF55605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D2835010000004847304402202329484C35FA9D6BB32A55A70C0982F606CE0E3634B69006138683BCD12CBB6602200C28FEB1E2555C3210F1DDDB299738B4FF8BBE9667B68CB8764B5AC17B7ADF0001FFFFFFFFFFFFFFFF0200E1F505000000004341046A0765B5865641CE08DD39690AADE26DFBF5511430CA428A3089261361CEF170E3929A68AEE3D8D4848B0C5111B0A37B82B86AD559FD2A745B44D8E8D9DFDC0CAC00180D8F000000004341044A656F065871A353F216CA26CEF8DDE2F03E8C16202D2E8AD769F02032CB86A5EB5E56842E92E19141D60A01928F8DD2C875A390F67C1F6C94CFC617C0EA45AFAC00000000000000000100000000000000 \ No newline at end of file +010000000255605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D28350000000049483045022100AA46504BAA86DF8A33B1192B1B9367B4D729DC41E389F2C04F3E5C7F0559AAE702205E82253A54BF5C4F65B7428551554B2045167D6D206DFE6A2E198127D3F7DF1501FFFFFFFFFFFFFFFF55605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D2835010000004847304402202329484C35FA9D6BB32A55A70C0982F606CE0E3634B69006138683BCD12CBB6602200C28FEB1E2555C3210F1DDDB299738B4FF8BBE9667B68CB8764B5AC17B7ADF0001FFFFFFFFFFFFFFFF0200E1F505000000004341046A0765B5865641CE08DD39690AADE26DFBF5511430CA428A3089261361CEF170E3929A68AEE3D8D4848B0C5111B0A37B82B86AD559FD2A745B44D8E8D9DFDC0CAC00180D8F000000004341044A656F065871A353F216CA26CEF8DDE2F03E8C16202D2E8AD769F02032CB86A5EB5E56842E92E19141D60A01928F8DD2C875A390F67C1F6C94CFC617C0EA45AFAC00000000000000000100000000000000000000000000000000000000 \ No newline at end of file diff --git a/util/txsort/testdata/bip69-3.hex b/util/txsort/testdata/bip69-3.hex index 63bad5993..9d91753bf 100644 --- a/util/txsort/testdata/bip69-3.hex +++ b/util/txsort/testdata/bip69-3.hex @@ -1 +1 @@ -0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffffffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000000000000100000000000000 \ No newline at end of file +0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffffffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000000000000100000000000000000000000000000000000000 \ No newline at end of file diff --git a/util/txsort/testdata/bip69-4.hex b/util/txsort/testdata/bip69-4.hex index c7dce767b..99072ec63 100644 --- a/util/txsort/testdata/bip69-4.hex +++ b/util/txsort/testdata/bip69-4.hex @@ -1 +1 @@ -01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffffffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000000000000100000000000000 \ No newline at end of file +01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffffffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000000000000100000000000000000000000000000000000000 \ No newline at end of file diff --git a/util/txsort/testdata/bip69-5.hex b/util/txsort/testdata/bip69-5.hex index 4632bd54c..48972346a 100644 --- a/util/txsort/testdata/bip69-5.hex +++ b/util/txsort/testdata/bip69-5.hex @@ -1 +1 @@ -01000000011f636d0003f673b3aeea4971daef16b8eed784cf6e8019a5ae7da4985fbb06e5000000008a47304402205103941e2b11e746dfa817888d422f6e7f4d16dbbfb8ffa61d15ffb924a84b8802202fe861b0f23f17139d15a3374bfc6c7196d371f3d1a324e31cc0aadbba87e53c0141049e7e1b251a7e26cae9ee7553b278ef58ef3c28b4b20134d51b747d9b18b0a19b94b66cef320e2549dec0ea3d725cb4c742f368928b1fb74b4603e24a1e262c80ffffffffffffffff0240420f00000000001976a914bcfa0e27218a7c97257b351b03a9eac95c25a23988ac40420f00000000001976a9140c6a68f20bafc678164d171ee4f077adfa9b091688ac00000000000000000100000000000000 \ No newline at end of file +01000000011f636d0003f673b3aeea4971daef16b8eed784cf6e8019a5ae7da4985fbb06e5000000008a47304402205103941e2b11e746dfa817888d422f6e7f4d16dbbfb8ffa61d15ffb924a84b8802202fe861b0f23f17139d15a3374bfc6c7196d371f3d1a324e31cc0aadbba87e53c0141049e7e1b251a7e26cae9ee7553b278ef58ef3c28b4b20134d51b747d9b18b0a19b94b66cef320e2549dec0ea3d725cb4c742f368928b1fb74b4603e24a1e262c80ffffffffffffffff0240420f00000000001976a914bcfa0e27218a7c97257b351b03a9eac95c25a23988ac40420f00000000001976a9140c6a68f20bafc678164d171ee4f077adfa9b091688ac00000000000000000100000000000000000000000000000000000000 \ No newline at end of file diff --git a/util/txsort/txsort_test.go b/util/txsort/txsort_test.go index 0cb21e26c..7b7ce0fb7 100644 --- a/util/txsort/txsort_test.go +++ b/util/txsort/txsort_test.go @@ -28,36 +28,36 @@ func TestSort(t *testing.T) { name: "first test case from BIP 69 - sorts inputs only, based on hash", hexFile: "bip69-1.hex", isSorted: false, - unsortedHash: "55721464fe5511e70792da14d7c4f20f6e81d5e7197919e536d0598796daaef3", - sortedHash: "573054025c067ab92e3e8b66cf25d16dbb8ab4ff9e9ef9ece79d2aee83f06785", + unsortedHash: "6b178242e9b6c1d448e2fa7d52fb7ec8dcea289c7852f1184880aabaef4da412", + sortedHash: "ab07dbc63d1376cfb4f122722748a9f1487adb66fbbb682c593da602723f22c3", }, { name: "second test case from BIP 69 - already sorted", hexFile: "bip69-2.hex", isSorted: true, - unsortedHash: "b9ce1181a9f94375000c9a49fc097a9abe9eb85a0f2e6792e1ec0ac24f72172b", - sortedHash: "b9ce1181a9f94375000c9a49fc097a9abe9eb85a0f2e6792e1ec0ac24f72172b", + unsortedHash: "ef51200d830bf2bc77b50e3b92f878d82f6f8d29d7e0d031782f24e2af023601", + sortedHash: "ef51200d830bf2bc77b50e3b92f878d82f6f8d29d7e0d031782f24e2af023601", }, { name: "block 100001 tx[1] - sorts outputs only, based on amount", hexFile: "bip69-3.hex", isSorted: false, - unsortedHash: "a1fd1029514fb555ecaa6126849d66a19c4239b2a77bdace6f6ef7db3cc23f30", - sortedHash: "4234b089ff83ec954b76e8b56449c095718124ebedd4cf8642d49f02ae55ade2", + unsortedHash: "36e32ff592786843a4b80dc1029129530e93c885a1cbeb9ef2bed309b336b92e", + sortedHash: "f971eb5dd57cc6848c0b903440c175a2fe0d93004099b1582e201de8d60ef6dc", }, { name: "block 100001 tx[2] - sorts both inputs and outputs", hexFile: "bip69-4.hex", isSorted: false, - unsortedHash: "d2eb3b56e3be83886dc5ee5789c332ba77f0f3f53abe98d306c1b2e9c25045a2", - sortedHash: "280567fe8d4cda60aa1d1b6ca87dd5944d761e8dee72a704af71365696988cda", + unsortedHash: "355b28a1b5e05c937755182169cbb6cfd58c9c50122ce430efb83c650c9aadef", + sortedHash: "4f0f023e7fc32a893fa156ca3001d1be4f1ff86f6d7b69d36f76fa0f427e765a", }, { name: "block 100998 tx[6] - sorts outputs only, based on output script", hexFile: "bip69-5.hex", isSorted: false, - unsortedHash: "5c83c1b03b7a1c80a44686323ea17d5bc60a976efb5a3de116cb99cac6ec2557", - sortedHash: "23c0abbbd17ca34980c9330e10b2c9230d72cec5aba38306ea676bbfa789a125", + unsortedHash: "f1d10b059664f8711d7a0960ce7763a89a89c697a74b8b5db4dbf850c0973fd6", + sortedHash: "76405dc7da88f622481b5e9d6894a45a45f7c376d1f95a390b8a494b7767ff71", }, } diff --git a/wire/message_test.go b/wire/message_test.go index 149ce73c5..14a6db0e0 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -91,11 +91,11 @@ func TestMessage(t *testing.T) { {msgGetAddr, msgGetAddr, pver, MainNet, 24}, {msgAddr, msgAddr, pver, MainNet, 25}, {msgGetBlocks, msgGetBlocks, pver, MainNet, 61}, - {msgBlock, msgBlock, pver, MainNet, 296}, + {msgBlock, msgBlock, pver, MainNet, 308}, {msgInv, msgInv, pver, MainNet, 25}, {msgGetData, msgGetData, pver, MainNet, 25}, {msgNotFound, msgNotFound, pver, MainNet, 25}, - {msgTx, msgTx, pver, MainNet, 46}, + {msgTx, msgTx, pver, MainNet, 58}, {msgPing, msgPing, pver, MainNet, 32}, {msgPong, msgPong, pver, MainNet, 32}, {msgGetHeaders, msgGetHeaders, pver, MainNet, 61}, diff --git a/wire/msgblock_test.go b/wire/msgblock_test.go index 9a8701869..977e06c05 100644 --- a/wire/msgblock_test.go +++ b/wire/msgblock_test.go @@ -72,7 +72,7 @@ func TestBlock(t *testing.T) { // hashes from a block accurately. func TestBlockTxHashes(t *testing.T) { // Block 1, transaction 1 hash. - hashStr := "603ea191aecb5809c78790a0bd58293086c1b19118e7251a38680dd9e1dc3b32" + hashStr := "f8f148865a0ecb895a2b8fffd37245b3d4f5e01213bdaaa38a52b74e2f3289b4" wantHash, err := daghash.NewHashFromStr(hashStr) if err != nil { t.Errorf("NewHashFromStr: %v", err) @@ -583,10 +583,12 @@ var blockOneBytes = []byte{ 0xee, // 65-byte uncompressed public key 0xac, // OP_CHECKSIG 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Subnetwork ID + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Subnetwork ID } // Transaction location information for block one transactions. var blockOneTxLocs = []TxLoc{ - {TxStart: 122, TxLen: 150}, + {TxStart: 122, TxLen: 162}, } diff --git a/wire/msgtx.go b/wire/msgtx.go index a5385e120..47543e06b 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -13,6 +13,7 @@ import ( "strconv" "github.com/daglabs/btcd/dagconfig/daghash" + "github.com/daglabs/btcd/util/subnetworkid" ) const ( @@ -96,15 +97,6 @@ const ( // 6,400,000 bytes. freeListMaxItems = 12500 - // SubNetworkSupportsAll is the sub-network id that is used to signal to peers that you support all sub-networks - SubNetworkSupportsAll = 0 - - // SubNetworkDAGCoin is the default sub-network which is used for transactions without related payload data - SubNetworkDAGCoin = 1 - - // SubNetworkRegistry is the sub-network which is used for adding new sub networks to the registry - SubNetworkRegistry = 2 - // SubNetworkReservedFirst and SubnetworkReservedLast mark the range of sub-networks that are reserved for future use // and are currently un-assigned for anything // SubNetworkReservedFirst is the first reserved sub-network @@ -114,6 +106,17 @@ const ( SubNetworkUnreservedFirst = 256 ) +var ( + // SubNetworkSupportsAll is the sub-network id that is used to signal to peers that you support all sub-networks + SubNetworkSupportsAll = subnetworkid.SubNetworkID{} + + // SubNetworkDAGCoin is the default sub-network which is used for transactions without related payload data + SubNetworkDAGCoin = subnetworkid.SubNetworkID{1} + + // SubNetworkRegistry is the sub-network which is used for adding new sub networks to the registry + SubNetworkRegistry = subnetworkid.SubNetworkID{2} +) + // scriptFreeList defines a free list of byte slices (up to the maximum number // defined by the freeListMaxItems constant) that have a cap according to the // freeListMaxScriptSize constant. It is used to provide temporary buffers for @@ -264,7 +267,7 @@ type MsgTx struct { TxIn []*TxIn TxOut []*TxOut LockTime uint64 - SubNetworkID uint64 + SubNetworkID subnetworkid.SubNetworkID Gas uint64 Payload []byte } @@ -463,7 +466,7 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error { return err } - msg.SubNetworkID, err = binarySerializer.Uint64(r, littleEndian) + _, err = io.ReadFull(r, msg.SubNetworkID[:]) if err != nil { returnScriptBuffers() return err @@ -613,7 +616,7 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32) error { return err } - err = binarySerializer.PutUint64(w, littleEndian, msg.SubNetworkID) + _, err = w.Write(msg.SubNetworkID[:]) if err != nil { return err } @@ -633,7 +636,10 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32) error { if err != nil { return err } - w.Write(msg.Payload) + _, err := w.Write(msg.Payload) + if err != nil { + return err + } } else if msg.Payload != nil { str := fmt.Sprintf("Transactions from subnetwork %v should have payload", msg.SubNetworkID) return messageError("MsgTx.BtcEncode", str) @@ -665,10 +671,10 @@ func (msg *MsgTx) Serialize(w io.Writer) error { // SerializeSize returns the number of bytes it would take to serialize the // the transaction. func (msg *MsgTx) SerializeSize() int { - // Version 4 bytes + LockTime 8 bytes + Subnetwork ID 8 + // Version 4 bytes + LockTime 8 bytes + Subnetwork ID 20 // bytes + Serialized varint size for the number of transaction // inputs and outputs. - n := 20 + VarIntSerializeSize(uint64(len(msg.TxIn))) + + n := 32 + VarIntSerializeSize(uint64(len(msg.TxIn))) + VarIntSerializeSize(uint64(len(msg.TxOut))) if msg.SubNetworkID != SubNetworkDAGCoin { diff --git a/wire/msgtx_test.go b/wire/msgtx_test.go index a60b0efd5..f51faf726 100644 --- a/wire/msgtx_test.go +++ b/wire/msgtx_test.go @@ -14,6 +14,7 @@ import ( "unsafe" "github.com/daglabs/btcd/dagconfig/daghash" + "github.com/daglabs/btcd/util/subnetworkid" "github.com/davecgh/go-spew/spew" ) @@ -130,7 +131,7 @@ func TestTx(t *testing.T) { // TestTxHash tests the ability to generate the hash of a transaction accurately. func TestTxHash(t *testing.T) { // Hash of first transaction from block 113875. - hashStr := "bc103ee9c89185146ba4e3eb9e936d46acd312cd8d2c5865fa4b0c02e67d0959" + hashStr := "2d0dd1e05410fe76afbd90f577f615d603ca00b2fa53f963e6375ce742343faa" wantHash, err := daghash.NewHashFromStr(hashStr) if err != nil { t.Errorf("NewHashFromStr: %v", err) @@ -186,7 +187,9 @@ func TestTxWire(t *testing.T) { 0x00, // Varint for number of input transactions 0x00, // Varint for number of output transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID } tests := []struct { @@ -198,7 +201,8 @@ func TestTxWire(t *testing.T) { // Latest protocol version with no transactions. { noTx, - noTx, noTxEncoded, + noTx, + noTxEncoded, ProtocolVersion, }, @@ -380,7 +384,9 @@ func TestTxSerialize(t *testing.T) { 0x00, // Varint for number of input transactions 0x00, // Varint for number of output transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID } registryTx := newRegistryMsgTx(1, 16) @@ -389,14 +395,16 @@ func TestTxSerialize(t *testing.T) { 0x00, // Varint for number of input transactions 0x00, // Varint for number of output transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Gas 0x08, // Payload length varint 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Payload / Gas limit } subNetworkTx := NewMsgTx(1) - subNetworkTx.SubNetworkID = 0xff + subNetworkTx.SubNetworkID = subnetworkid.SubNetworkID{0xff} subNetworkTx.Gas = 5 subNetworkTx.Payload = []byte{0, 1, 2} @@ -405,7 +413,9 @@ func TestTxSerialize(t *testing.T) { 0x00, // Varint for number of input transactions 0x00, // Varint for number of output transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Gas 0x03, // Payload length varint 0x00, 0x01, 0x02, // Payload @@ -597,7 +607,9 @@ func TestTxSerializeErrors(t *testing.T) { 0x00, // Varint for number of input transactions 0x00, // Varint for number of output transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Gas 0x08, // Payload length varint 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Payload / Gas limit @@ -607,7 +619,7 @@ func TestTxSerializeErrors(t *testing.T) { var tx MsgTx err = tx.Deserialize(r) - str = fmt.Sprintf("%v is a reserved sub network and cannot be used as part of a transaction", 0) + str = fmt.Sprintf("%v is a reserved sub network and cannot be used as part of a transaction", SubNetworkSupportsAll) expectedErr = messageError("MsgTx.BtcDecode", str) if err == nil || err.Error() != expectedErr.Error() { t.Errorf("TestTxSerializeErrors: expected error %v but got %v", expectedErr, err) @@ -618,7 +630,9 @@ func TestTxSerializeErrors(t *testing.T) { 0x00, // Varint for number of input transactions 0x00, // Varint for number of output transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Gas 0x08, // Payload length varint 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Payload / Gas limit @@ -638,7 +652,9 @@ func TestTxSerializeErrors(t *testing.T) { 0x00, // Varint for number of input transactions 0x00, // Varint for number of output transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Gas 0x03, // Payload length varint 0x01, 0x02, 0x03, // Payload / Gas limit @@ -762,10 +778,10 @@ func TestTxSerializeSize(t *testing.T) { size int // Expected serialized size }{ // No inputs or outpus. - {noTx, 22}, + {noTx, 34}, // Transcaction with an input and an output. - {multiTx, 226}, + {multiTx, 238}, } t.Logf("Running %d tests", len(tests)) @@ -942,7 +958,9 @@ var multiTxEncoded = []byte{ 0xa6, // 65-byte signature 0xac, // OP_CHECKSIG 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub Network ID + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Sub Network ID } // multiTxPkScriptLocs is the location information for the public key scripts From 5171d26bbae0b0e08ec36007191f600f0db19e72 Mon Sep 17 00:00:00 2001 From: stasatdaglabs <39559713+stasatdaglabs@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:13:11 +0200 Subject: [PATCH 2/2] [DEV-343] Change SubNetworkRegistry to use SubNetworkID as Hash160 (#156) * [DEV-343] Made sub-network registry use subNetworkIDs. * [DEV-343] Removed an unnecessary clone. * [DEV-343] Renamed buildSubNetworkID to txToSubNetworkID. Broke out of a loop when it was known that no further processing is required. Handled error cases from dbGetNetwork separately from the "not-found" case/ * [DEV-343] Added an error case in GasLimit() for where the sub-network is nil. * [DEV-343] Fixed return nil instead of err. Used a better way to check whether we should continue checking accepted transactions. --- blockdag/dag.go | 28 +--- blockdag/dagio.go | 3 - blockdag/subnetworks.go | 294 +++++++---------------------------- blockdag/subnetworks_test.go | 105 ++----------- blockdag/test_utils.go | 40 ++--- config/config.go | 2 +- mempool/mempool.go | 4 +- mempool/mempool_test.go | 15 +- mining/mining.go | 14 +- wire/msgtx.go | 8 - 10 files changed, 103 insertions(+), 410 deletions(-) diff --git a/blockdag/dag.go b/blockdag/dag.go index 7d26ed5e6..68f061acf 100644 --- a/blockdag/dag.go +++ b/blockdag/dag.go @@ -516,8 +516,6 @@ func (dag *BlockDAG) connectBlock(node *blockNode, block *util.Block, fastAdd bo } } - initialFinalityPoint := dag.lastFinalityPoint - var finalityPointCandidate *blockNode if !fastAdd { var err error @@ -537,14 +535,6 @@ func (dag *BlockDAG) connectBlock(node *blockNode, block *util.Block, fastAdd bo dag.lastFinalityPoint = finalityPointCandidate } - // Scan all accepted transactions and collect any sub-network registry - // transactions into subNetworkRegistryTxs. If any sub-network registry - // transaction is not well-formed, fail the entire block. - subNetworkRegistryTxs, err := validateAndExtractSubNetworkRegistryTxs(acceptedTxsData) - if err != nil { - return err - } - // Write any block status changes to DB before updating the DAG state. err = dag.index.flushToDB() if err != nil { @@ -557,7 +547,6 @@ func (dag *BlockDAG) connectBlock(node *blockNode, block *util.Block, fastAdd bo state := &dagState{ TipHashes: dag.TipHashes(), LastFinalityPoint: dag.lastFinalityPoint.hash, - LastSubNetworkID: dag.lastSubNetworkID, } err := dbPutDAGState(dbTx, state) if err != nil { @@ -578,22 +567,14 @@ func (dag *BlockDAG) connectBlock(node *blockNode, block *util.Block, fastAdd bo return err } - // Add the pending sub-network in this block to the pending sub-networks - // collection. - err = dbPutPendingSubNetworkTxs(dbTx, block.Hash(), subNetworkRegistryTxs) + // Scan all accepted transactions and register any sub-network registry + // transaction. If any sub-network registry transaction is not well-formed, + // fail the entire block. + err = registerSubNetworks(dbTx, acceptedTxsData) if err != nil { return err } - // Register all pending sub-networks between the initial finality point and - // the new one. - if initialFinalityPoint != dag.lastFinalityPoint { - err = dag.registerPendingSubNetworks(dbTx, initialFinalityPoint, dag.lastFinalityPoint) - if err != nil { - return err - } - } - // Allow the index manager to call each of the currently active // optional indexes with the block being connected so they can // update themselves accordingly. @@ -1603,7 +1584,6 @@ func New(config *Config) (*BlockDAG, error) { warningCaches: newThresholdCaches(vbNumBits), deploymentCaches: newThresholdCaches(dagconfig.DefinedDeployments), blockCount: 1, - lastSubNetworkID: wire.SubNetworkUnreservedFirst, } // Initialize the chain state from the passed database. When the db diff --git a/blockdag/dagio.go b/blockdag/dagio.go index 4be7d33d4..3a916c80f 100644 --- a/blockdag/dagio.go +++ b/blockdag/dagio.go @@ -992,9 +992,6 @@ func (dag *BlockDAG) initDAGState() error { // Set the last finality point dag.lastFinalityPoint = dag.index.LookupNode(&state.LastFinalityPoint) - // Set the last sub-network ID - dag.lastSubNetworkID = state.LastSubNetworkID - return nil }) } diff --git a/blockdag/subnetworks.go b/blockdag/subnetworks.go index 4a90b5285..9544c3771 100644 --- a/blockdag/subnetworks.go +++ b/blockdag/subnetworks.go @@ -4,29 +4,57 @@ import ( "bytes" "encoding/binary" "fmt" + "github.com/daglabs/btcd/util" - "github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/database" "github.com/daglabs/btcd/util/subnetworkid" "github.com/daglabs/btcd/wire" ) -// validateAndExtractSubNetworkRegistryTxs filters the given input and extracts a list -// of valid sub-network registry transactions. -func validateAndExtractSubNetworkRegistryTxs(txs []*TxWithBlockHash) ([]*wire.MsgTx, error) { +// registerSubNetworks scans a list of accepted transactions, singles out +// sub-network registry transactions, validates them, and registers a new +// sub-network based on it. +// This function returns an error if one or more transactions are invalid +func registerSubNetworks(dbTx database.Tx, txs []*TxWithBlockHash) error { validSubNetworkRegistryTxs := make([]*wire.MsgTx, 0) for _, txData := range txs { tx := txData.Tx.MsgTx() if tx.SubNetworkID == wire.SubNetworkRegistry { err := validateSubNetworkRegistryTransaction(tx) if err != nil { - return nil, err + return err } validSubNetworkRegistryTxs = append(validSubNetworkRegistryTxs, tx) } + + if subnetworkid.Less(&wire.SubNetworkRegistry, &tx.SubNetworkID) { + // Transactions are ordered by sub-network, so we can safely assume + // that the rest of the transactions will not be sub-network registry + // transactions. + break + } } - return validSubNetworkRegistryTxs, nil + for _, registryTx := range validSubNetworkRegistryTxs { + subNetworkID, err := txToSubNetworkID(registryTx) + if err != nil { + return err + } + sNet, err := dbGetSubNetwork(dbTx, subNetworkID) + if err != nil { + return err + } + if sNet == nil { + createdSubNetwork := newSubNetwork(registryTx) + err := dbRegisterSubNetwork(dbTx, subNetworkID, createdSubNetwork) + if err != nil { + return fmt.Errorf("failed registering sub-network"+ + "for tx '%s': %s", registryTx.TxHash(), err) + } + } + } + + return nil } // validateSubNetworkRegistryTransaction makes sure that a given sub-network registry @@ -41,66 +69,15 @@ func validateSubNetworkRegistryTransaction(tx *wire.MsgTx) error { return nil } -// registerPendingSubNetworks attempts to register all the pending sub-networks that -// had previously been defined between the initial finality point and the new one. -// Note: transactions within newFinalityPoint itself are not registered. Instead, they will -// be registered when the next finality point is chosen; then it will be the -// initialFinalityPoint. -func (dag *BlockDAG) registerPendingSubNetworks(dbTx database.Tx, initialFinalityPoint *blockNode, newFinalityPoint *blockNode) error { - var stack []*blockNode - for currentNode := newFinalityPoint; currentNode != initialFinalityPoint; currentNode = currentNode.selectedParent { - stack = append(stack, currentNode) - } - - // Register a pending sub-network for all blues. The block itself is not explicitly - // registered since it will be one of the blues of the next block. - // Note that this means that the very last block in the selected parent chain is not - // registered. This is intentional. - for i := len(stack) - 1; i >= 0; i-- { - currentNode := stack[i] - for _, blue := range currentNode.blues { - err := dag.registerPendingSubNetworksInBlock(dbTx, blue.hash) - if err != nil { - return fmt.Errorf("failed to register pending sub-networks: %s", err) - } - } - } - - return nil +// txToSubNetworkID creates a sub-network ID from a sub-network registry transaction +func txToSubNetworkID(tx *wire.MsgTx) (*subnetworkid.SubNetworkID, error) { + txHash := tx.TxHash() + return subnetworkid.New(util.Hash160(txHash[:])) } -// registerPendingSubNetworksInBlock attempts to register all the sub-networks -// that had been defined in a given block. -func (dag *BlockDAG) registerPendingSubNetworksInBlock(dbTx database.Tx, blockHash daghash.Hash) error { - pendingSubNetworkTxs, err := dbGetPendingSubNetworkTxs(dbTx, blockHash) - if err != nil { - return fmt.Errorf("failed to retrieve pending sub-network txs in block '%s': %s", blockHash, err) - } - for _, tx := range pendingSubNetworkTxs { - if !dbIsRegisteredSubNetworkTx(dbTx, tx.TxHash()) { - createdSubNetwork := newSubNetwork(tx) - err := dbRegisterSubNetwork(dbTx, dag.lastSubNetworkID, tx.TxHash(), createdSubNetwork) - if err != nil { - return fmt.Errorf("failed registering sub-network"+ - "for tx '%s' in block '%s': %s", tx.TxHash(), blockHash, err) - } - - dag.lastSubNetworkID++ - } - } - - err = dbRemovePendingSubNetworkTxs(dbTx, blockHash) - if err != nil { - return fmt.Errorf("failed to remove block '%s'"+ - "from pending sub-networks: %s", blockHash, err) - } - - return nil -} - -// subNetwork returns a registered-and-finalized sub-network. If the sub-network -// does not exist this method returns an error. -func (dag *BlockDAG) subNetwork(subNetworkID subnetworkid.SubNetworkID) (*subNetwork, error) { +// subNetwork returns a registered sub-network. If the sub-network does not exist +// this method returns an error. +func (dag *BlockDAG) subNetwork(subNetworkID *subnetworkid.SubNetworkID) (*subNetwork, error) { var sNet *subNetwork var err error dbErr := dag.db.View(func(dbTx database.Tx) error { @@ -117,213 +94,70 @@ func (dag *BlockDAG) subNetwork(subNetworkID subnetworkid.SubNetworkID) (*subNet return sNet, nil } -// GasLimit returns the gas limit of a registered-and-finalized sub-network. If -// the sub-network does not exist this method returns an error. -func (dag *BlockDAG) GasLimit(subNetworkID subnetworkid.SubNetworkID) (uint64, error) { +// GasLimit returns the gas limit of a registered sub-network. If the sub-network does not +// exist this method returns an error. +func (dag *BlockDAG) GasLimit(subNetworkID *subnetworkid.SubNetworkID) (uint64, error) { sNet, err := dag.subNetwork(subNetworkID) if err != nil { return 0, err } + if sNet == nil { + return 0, fmt.Errorf("sub-network '%s' not found", subNetworkID) + } return sNet.gasLimit, nil } -// ----------------------------------------------------------------------------- -// The sub-network registry consists of three buckets: -// a. The pending sub-network bucket -// b. The registered transaction bucket -// c. The sub-network bucket -// -// All newly-discovered sub-network registry transactions are stored in the -// pending sub-network bucket. These transactions are withheld until the -// blocks that contain them become final. -// -// Once the block of a sub-network registry transaction becomes final, all the -// transactions within that block are retrieved and checked for validity. -// Valid transactions are then: -// 1. Assigned a sub-network ID -// 2. Added to the registered transaction bucket -// 3. Added to the sub-network bucket -// ----------------------------------------------------------------------------- - -// dbPutPendingSubNetworkTxs stores mappings from a block (via its hash) to an -// array of sub-network transactions. -func dbPutPendingSubNetworkTxs(dbTx database.Tx, blockHash *daghash.Hash, subNetworkRegistryTxs []*wire.MsgTx) error { - // Empty blocks are not written - if len(subNetworkRegistryTxs) == 0 { - return nil - } - - serializedTxs, err := serializeSubNetworkRegistryTxs(subNetworkRegistryTxs) - if err != nil { - return fmt.Errorf("failed to serialize pending sub-network txs in block '%s': %s", blockHash, err) - } - - // Store the serialized transactions - bucket := dbTx.Metadata().Bucket(pendingSubNetworksBucketName) - err = bucket.Put(blockHash[:], serializedTxs) - if err != nil { - return fmt.Errorf("failed to write pending sub-network txs in block '%s': %s", blockHash, err) - } - - return nil -} - -// dbGetPendingSubNetworkTxs retrieves an array of sub-network transactions, -// associated with a block's hash, that was previously stored with -// dbPutPendingSubNetworkTxs. -// Returns an empty slice if the hash was not previously stored. -func dbGetPendingSubNetworkTxs(dbTx database.Tx, blockHash daghash.Hash) ([]*wire.MsgTx, error) { - bucket := dbTx.Metadata().Bucket(pendingSubNetworksBucketName) - serializedTxsBytes := bucket.Get(blockHash[:]) - if serializedTxsBytes == nil { - return []*wire.MsgTx{}, nil - } - - txs, err := deserializeSubNetworkRegistryTxs(serializedTxsBytes) - if err != nil { - return nil, fmt.Errorf("failed to deserialize pending sub-network txs for block '%s': %s", blockHash, err) - } - - return txs, nil -} - -// serializeSubNetworkRegistryTxs serializes a slice of MsgTxs by serializing each transaction -// individually and appending it to one long byte slice. -func serializeSubNetworkRegistryTxs(subNetworkRegistryTxs []*wire.MsgTx) ([]byte, error) { - // Calculate the length in bytes of the serialized transactions - serializedTxsLength := uint64(0) - for _, tx := range subNetworkRegistryTxs { - serializedTxsLength += uint64(tx.SerializeSize()) - } - serializedTxs := bytes.NewBuffer(make([]byte, 0, serializedTxsLength)) - - // Write each transaction in the order it appears in - for _, tx := range subNetworkRegistryTxs { - err := tx.Serialize(serializedTxs) - if err != nil { - return nil, fmt.Errorf("failed to serialize tx '%s': %s", tx.TxHash(), err) - } - } - - return serializedTxs.Bytes(), nil -} - -// deserializeSubNetworkRegistryTxs deserializes a byte slice into a slice of MsgTxs. -func deserializeSubNetworkRegistryTxs(serializedTxsBytes []byte) ([]*wire.MsgTx, error) { - serializedTxs := bytes.NewBuffer(serializedTxsBytes) - - // Read each transaction and store it in txs until the end of the buffer - txs := make([]*wire.MsgTx, 0) - for serializedTxs.Len() > 0 { - var tx wire.MsgTx - err := tx.Deserialize(serializedTxs) - if err != nil { - return nil, fmt.Errorf("failed to deserialize pending sub-network txs: %s", err) - } - - txs = append(txs, &tx) - } - - return txs, nil -} - -// dbRemovePendingSubNetworkTxs deletes an array of sub-network transactions, -// associated with a block's hash, that was previously stored with -// dbPutPendingSubNetworkTxs. -// This function does not return an error if the hash was not previously stored. -func dbRemovePendingSubNetworkTxs(dbTx database.Tx, blockHash daghash.Hash) error { - bucket := dbTx.Metadata().Bucket(pendingSubNetworksBucketName) - - err := bucket.Delete(blockHash[:]) - if err != nil { - return fmt.Errorf("failed to remove pending sub-network txs in block '%s': %s", blockHash, err) - } - - return nil -} - -// dbIsRegisteredSubNetworkTx checks whether a sub-network registry transaction -// had successfully registered a sub-network. -func dbIsRegisteredSubNetworkTx(dbTx database.Tx, txHash daghash.Hash) bool { - bucket := dbTx.Metadata().Bucket(registeredSubNetworkTxsBucketName) - subNetworkIDBytes := bucket.Get(txHash[:]) - - return subNetworkIDBytes != nil -} - -// dbRegisterSubNetwork stores mappings: -// a. from the ID of the sub-network to the sub-network data. -// b. from the hash of a sub-network registry transaction to the sub-network ID. -func dbRegisterSubNetwork(dbTx database.Tx, subNetworkID uint64, txHash daghash.Hash, network *subNetwork) error { - // Serialize the sub-network ID - subNetworkIDBytes := make([]byte, 8) - byteOrder.PutUint64(subNetworkIDBytes, subNetworkID) - +// dbRegisterSubNetwork stores mappings from ID of the sub-network to the sub-network data. +func dbRegisterSubNetwork(dbTx database.Tx, subNetworkID *subnetworkid.SubNetworkID, network *subNetwork) error { // Serialize the sub-network serializedSubNetwork, err := serializeSubNetwork(network) if err != nil { - return fmt.Errorf("failed to serialize sub-netowrk of tx '%s': %s", network.txHash, err) + return fmt.Errorf("failed to serialize sub-netowrk '%s': %s", subNetworkID, err) } // Store the sub-network subNetworksBucket := dbTx.Metadata().Bucket(subNetworksBucketName) - err = subNetworksBucket.Put(subNetworkIDBytes, serializedSubNetwork) + err = subNetworksBucket.Put(subNetworkID[:], serializedSubNetwork) if err != nil { - return fmt.Errorf("failed to write sub-netowrk of tx '%s': %s", network.txHash, err) - } - - // Store the mapping between txHash and subNetworkID - registeredSubNetworkTxs := dbTx.Metadata().Bucket(registeredSubNetworkTxsBucketName) - err = registeredSubNetworkTxs.Put(txHash[:], subNetworkIDBytes) - if err != nil { - return fmt.Errorf("failed to put registered sub-networkTx '%s': %s", txHash, err) + return fmt.Errorf("failed to write sub-netowrk '%s': %s", subNetworkID, err) } return nil } -func dbGetSubNetwork(dbTx database.Tx, subNetworkID subnetworkid.SubNetworkID) (*subNetwork, error) { - // Get the sub-network +// dbGetSubNetwork returns the sub-network associated with subNetworkID or nil if the sub-network was not found. +func dbGetSubNetwork(dbTx database.Tx, subNetworkID *subnetworkid.SubNetworkID) (*subNetwork, error) { bucket := dbTx.Metadata().Bucket(subNetworksBucketName) serializedSubNetwork := bucket.Get(subNetworkID[:]) if serializedSubNetwork == nil { - return nil, fmt.Errorf("sub-network '%d' not found", subNetworkID) + return nil, nil } return deserializeSubNetwork(serializedSubNetwork) } type subNetwork struct { - txHash daghash.Hash gasLimit uint64 } func newSubNetwork(tx *wire.MsgTx) *subNetwork { - txHash := tx.TxHash() gasLimit := binary.LittleEndian.Uint64(tx.Payload[:8]) return &subNetwork{ - txHash: txHash, gasLimit: gasLimit, } } // serializeSubNetwork serializes a subNetwork into the following binary format: -// | txHash (32 bytes) | gasLimit (8 bytes) | +// | gasLimit (8 bytes) | func serializeSubNetwork(sNet *subNetwork) ([]byte, error) { - serializedSNet := bytes.NewBuffer(make([]byte, 0, 40)) - - // Write the tx hash - err := binary.Write(serializedSNet, byteOrder, sNet.txHash) - if err != nil { - return nil, fmt.Errorf("failed to serialize sub-network for tx '%s': %s", sNet.txHash, err) - } + serializedSNet := bytes.NewBuffer(make([]byte, 0, 8)) // Write the gas limit - err = binary.Write(serializedSNet, byteOrder, sNet.gasLimit) + err := binary.Write(serializedSNet, byteOrder, sNet.gasLimit) if err != nil { - return nil, fmt.Errorf("failed to serialize sub-network for tx '%s': %s", sNet.txHash, err) + return nil, fmt.Errorf("failed to serialize sub-network: %s", err) } return serializedSNet.Bytes(), nil @@ -334,22 +168,14 @@ func serializeSubNetwork(sNet *subNetwork) ([]byte, error) { func deserializeSubNetwork(serializedSNetBytes []byte) (*subNetwork, error) { serializedSNet := bytes.NewBuffer(serializedSNetBytes) - // Read the tx hash - var txHash daghash.Hash - err := binary.Read(serializedSNet, byteOrder, &txHash) - if err != nil { - return nil, fmt.Errorf("failed to deserialize sub-network: %s", err) - } - // Read the gas limit var gasLimit uint64 - err = binary.Read(serializedSNet, byteOrder, &gasLimit) + err := binary.Read(serializedSNet, byteOrder, &gasLimit) if err != nil { return nil, fmt.Errorf("failed to deserialize sub-network: %s", err) } return &subNetwork{ - txHash: txHash, gasLimit: gasLimit, }, nil } diff --git a/blockdag/subnetworks_test.go b/blockdag/subnetworks_test.go index e5fd370b6..8d0d3f34c 100644 --- a/blockdag/subnetworks_test.go +++ b/blockdag/subnetworks_test.go @@ -1,23 +1,17 @@ package blockdag import ( - "encoding/binary" - "math" "reflect" "testing" "github.com/daglabs/btcd/dagconfig" - "github.com/daglabs/btcd/wire" ) -// TestSubNetworkRegistry tests the full sub-network registry flow. In this test: -// 1. We create a sub-network registry transaction and add its block to the DAG -// 2. Add 2*finalityInterval so that the sub-network registry transaction becomes final -// 3. Attempt to retrieve the gas limit of the now-registered sub-network +// TestSubNetworkRegistry tests the full sub-network registry flow func TestSubNetworkRegistry(t *testing.T) { params := dagconfig.SimNetParams params.K = 1 - dag, teardownFunc, err := DAGSetup("TestFinality", Config{ + dag, teardownFunc, err := DAGSetup("TestSubNetworkRegistry", Config{ DAGParams: ¶ms, }) if err != nil { @@ -25,103 +19,22 @@ func TestSubNetworkRegistry(t *testing.T) { } defer teardownFunc() - _, err = RegisterSubnetworkForTest(dag, 12345) - + gasLimit := uint64(12345) + subNetworkID, err := RegisterSubNetworkForTest(dag, gasLimit) if err != nil { t.Fatalf("could not register network: %s", err) } -} - -func TestSerializeSubNetworkRegistryTxs(t *testing.T) { - payload1 := make([]byte, 8) - binary.LittleEndian.PutUint64(payload1, uint64(100)) - tx1 := wire.MsgTx{ - Version: 1, - SubNetworkID: wire.SubNetworkRegistry, - Payload: payload1, - TxIn: []*wire.TxIn{ - { - PreviousOutPoint: wire.OutPoint{ - Hash: *newHashFromStr("0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9"), - Index: 0, - }, - SignatureScript: hexToBytes("47304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901"), - Sequence: math.MaxUint64, - }, - }, - TxOut: []*wire.TxOut{{ - Value: 1000000000, - PkScript: hexToBytes("4104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac"), - }, { - Value: 4000000000, - PkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), - }}, + limit, err := dag.GasLimit(subNetworkID) + if err != nil { + t.Fatalf("could not retrieve gas limit: %s", err) } - - payload2 := make([]byte, 8) - binary.LittleEndian.PutUint64(payload2, uint64(200)) - tx2 := wire.MsgTx{ - Version: 1, - SubNetworkID: wire.SubNetworkRegistry, - Payload: payload2, - TxIn: []*wire.TxIn{{ - PreviousOutPoint: wire.OutPoint{ - Hash: *newHashFromStr("0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9"), - Index: 0, - }, - SignatureScript: hexToBytes("47304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901"), - Sequence: math.MaxUint64, - }}, - TxOut: []*wire.TxOut{{ - Value: 5000000, - PkScript: hexToBytes("76a914f419b8db4ba65f3b6fcc233acb762ca6f51c23d488ac"), - }, { - Value: 34400000000, - PkScript: hexToBytes("76a914cadf4fc336ab3c6a4610b75f31ba0676b7f663d288ac"), - }}, - LockTime: 0, - } - - tests := []struct { - name string - txs []*wire.MsgTx - }{ - { - name: "empty slice", - txs: []*wire.MsgTx{}, - }, - { - name: "one transaction", - txs: []*wire.MsgTx{&tx1}, - }, - { - name: "two transactions", - txs: []*wire.MsgTx{&tx2, &tx1}, - }, - } - - for _, test := range tests { - serializedTxs, err := serializeSubNetworkRegistryTxs(test.txs) - if err != nil { - t.Errorf("serialization in test '%s' unexpectedly failed: %s", test.name, err) - continue - } - - deserializedTxs, err := deserializeSubNetworkRegistryTxs(serializedTxs) - if err != nil { - t.Errorf("deserialization in test '%s' unexpectedly failed: %s", test.name, err) - continue - } - - if !reflect.DeepEqual(test.txs, deserializedTxs) { - t.Errorf("original txs and deserialized txs are not equal in test '%s'", test.name) - } + if limit != gasLimit { + t.Fatalf("unexpected gas limit. want: %d, got: %d", gasLimit, limit) } } func TestSerializeSubNetwork(t *testing.T) { sNet := &subNetwork{ - txHash: *newHashFromStr("0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9"), gasLimit: 1000, } diff --git a/blockdag/test_utils.go b/blockdag/test_utils.go index 5cb794a6a..a1b4a783a 100644 --- a/blockdag/test_utils.go +++ b/blockdag/test_utils.go @@ -3,6 +3,7 @@ package blockdag import ( "encoding/binary" "fmt" + "github.com/daglabs/btcd/util/subnetworkid" "os" "path/filepath" "time" @@ -143,9 +144,9 @@ func createCoinbaseTxForTest(blockHeight int32, numOutputs uint32, extraNonce in return tx, nil } -// RegisterSubnetworkForTest is used to register network on DAG with specified GAS limit. -func RegisterSubnetworkForTest(dag *BlockDAG, gasLimit uint64) (subNetworkID uint64, err error) { - blockTime := time.Unix(dag.genesis.timestamp, 0) +// RegisterSubNetworkForTest is used to register network on DAG with specified gas limit +func RegisterSubNetworkForTest(dag *BlockDAG, gasLimit uint64) (*subnetworkid.SubNetworkID, error) { + blockTime := time.Unix(dag.selectedTip().timestamp, 0) extraNonce := int64(0) buildNextBlock := func(parents blockSet, txs []*wire.MsgTx) (*util.Block, error) { @@ -180,7 +181,7 @@ func RegisterSubnetworkForTest(dag *BlockDAG, gasLimit uint64) (subNetworkID uin dag.dagLock.Lock() defer dag.dagLock.Unlock() - err = dag.maybeAcceptBlock(block, BFNone) + err := dag.maybeAcceptBlock(block, BFNone) if err != nil { return nil, err } @@ -188,7 +189,7 @@ func RegisterSubnetworkForTest(dag *BlockDAG, gasLimit uint64) (subNetworkID uin return dag.index.LookupNode(block.Hash()), nil } - currentNode := dag.genesis + currentNode := dag.selectedTip() // Create a block with a valid sub-network registry transaction registryTx := wire.NewMsgTx(wire.TxVersion) @@ -199,34 +200,17 @@ func RegisterSubnetworkForTest(dag *BlockDAG, gasLimit uint64) (subNetworkID uin // Add it to the DAG registryBlock, err := buildNextBlock(setFromSlice(currentNode), []*wire.MsgTx{registryTx}) if err != nil { - return 0, fmt.Errorf("could not build registry block: %s", err) + return nil, fmt.Errorf("could not build registry block: %s", err) } currentNode, err = addBlockToDAG(registryBlock) if err != nil { - return 0, fmt.Errorf("could not add registry block to DAG: %s", err) + return nil, fmt.Errorf("could not add registry block to DAG: %s", err) } - // Add 2*finalityInterval to ensure the registry transaction is finalized - for currentNode.blueScore < 2*finalityInterval { - nextBlock, err := buildNextBlock(setFromSlice(currentNode), []*wire.MsgTx{}) - if err != nil { - return 0, fmt.Errorf("could not create block: %s", err) - } - currentNode, err = addBlockToDAG(nextBlock) - if err != nil { - return 0, fmt.Errorf("could not add block to DAG: %s", err) - } - } - - // Make sure that the sub-network had been successfully registered by trying - // to retrieve its gas limit. - mostRecentlyRegisteredSubNetworkID := dag.lastSubNetworkID - 1 - limit, err := dag.GasLimit(mostRecentlyRegisteredSubNetworkID) + // Build a sub-network ID from the registry transaction + subNetworkID, err := txToSubNetworkID(registryTx) if err != nil { - return 0, fmt.Errorf("could not retrieve gas limit: %s", err) + return nil, fmt.Errorf("could not build sub-network ID: %s", err) } - if limit != gasLimit { - return 0, fmt.Errorf("unexpected gas limit. want: %d, got: %d", gasLimit, limit) - } - return mostRecentlyRegisteredSubNetworkID, nil + return subNetworkID, nil } diff --git a/config/config.go b/config/config.go index 3a68ea936..ae6574053 100644 --- a/config/config.go +++ b/config/config.go @@ -754,7 +754,7 @@ func loadConfig() (*Config, []string, error) { } if cfg.configFlags.SubNetwork != "" { - cfg.SubNetwork, err = subnetworkid.NewIDFromStr(cfg.configFlags.SubNetwork) + cfg.SubNetwork, err = subnetworkid.NewFromStr(cfg.configFlags.SubNetwork) if err != nil { return nil, nil, err } diff --git a/mempool/mempool.go b/mempool/mempool.go index 9ad5ceab3..35fbb1ff4 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -659,10 +659,10 @@ func (mp *TxPool) maybeAcceptTransaction(tx *util.Tx, isNew, rateLimit, rejectDu // Check that transaction does not overuse GAS msgTx := tx.MsgTx() - if msgTx.SubNetworkID == 0 { + if msgTx.SubNetworkID == wire.SubNetworkSupportsAll { return nil, nil, txRuleError(wire.RejectInvalid, "Subnetwork 0 is not permited in transaction") } else if msgTx.SubNetworkID != wire.SubNetworkDAGCoin { - gasLimit, err := mp.cfg.DAG.GasLimit(msgTx.SubNetworkID) + gasLimit, err := mp.cfg.DAG.GasLimit(&msgTx.SubNetworkID) if err != nil { return nil, nil, err } diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 1756e765d..23115f93e 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -9,6 +9,7 @@ import ( "encoding/hex" "errors" "fmt" + "github.com/daglabs/btcd/util/subnetworkid" "math" "reflect" "runtime" @@ -155,11 +156,11 @@ func (p *poolHarness) CreateCoinbaseTx(blockHeight int32, numOutputs uint32) (*u return util.NewTx(tx), nil } -// CreateSignedTxForSubnetwork creates a new signed transaction that consumes the provided +// CreateSignedTxForSubNetwork creates a new signed transaction that consumes the provided // inputs and generates the provided number of outputs by evenly splitting the // total input amount. All outputs will be to the payment script associated // with the harness and all inputs are assumed to do the same. -func (p *poolHarness) CreateSignedTxForSubnetwork(inputs []spendableOutpoint, numOutputs uint32, subnetworkID uint64, gas uint64) (*util.Tx, error) { +func (p *poolHarness) CreateSignedTxForSubNetwork(inputs []spendableOutpoint, numOutputs uint32, subNetworkID *subnetworkid.SubNetworkID, gas uint64) (*util.Tx, error) { // Calculate the total input amount and split it amongst the requested // number of outputs. var totalInput util.Amount @@ -170,7 +171,7 @@ func (p *poolHarness) CreateSignedTxForSubnetwork(inputs []spendableOutpoint, nu remainder := uint64(totalInput) - amountPerOutput*uint64(numOutputs) tx := wire.NewMsgTx(wire.TxVersion) - tx.SubNetworkID = subnetworkID + tx.SubNetworkID = *subNetworkID tx.Gas = gas for _, input := range inputs { tx.AddTxIn(&wire.TxIn{ @@ -210,7 +211,7 @@ func (p *poolHarness) CreateSignedTxForSubnetwork(inputs []spendableOutpoint, nu // total input amount. All outputs will be to the payment script associated // with the harness and all inputs are assumed to do the same. func (p *poolHarness) CreateSignedTx(inputs []spendableOutpoint, numOutputs uint32) (*util.Tx, error) { - return p.CreateSignedTxForSubnetwork(inputs, numOutputs, wire.SubNetworkDAGCoin, 0) + return p.CreateSignedTxForSubNetwork(inputs, numOutputs, &wire.SubNetworkDAGCoin, 0) } // CreateTxChain creates a chain of zero-fee transactions (each subsequent @@ -1843,13 +1844,13 @@ func TestTransactionGas(t *testing.T) { // tc := &testContext{t, harness} const gasLimit = 10000 - subnetworkID, err := blockdag.RegisterSubnetworkForTest(harness.txPool.cfg.DAG, gasLimit) + subNetworkID, err := blockdag.RegisterSubNetworkForTest(harness.txPool.cfg.DAG, gasLimit) if err != nil { t.Fatalf("unable to register network: %v", err) } // Create valid transaction - tx, err := harness.CreateSignedTxForSubnetwork(spendableOuts[:1], 1, subnetworkID, gasLimit) + tx, err := harness.CreateSignedTxForSubNetwork(spendableOuts[:1], 1, subNetworkID, gasLimit) if err != nil { t.Fatalf("unable to create transaction: %v", err) } @@ -1859,7 +1860,7 @@ func TestTransactionGas(t *testing.T) { } // Create invalid transaction - tx, err = harness.CreateSignedTxForSubnetwork(spendableOuts[1:], 1, subnetworkID, gasLimit+1) + tx, err = harness.CreateSignedTxForSubNetwork(spendableOuts[1:], 1, subNetworkID, gasLimit+1) if err != nil { t.Fatalf("unable to create transaction: %v", err) } diff --git a/mining/mining.go b/mining/mining.go index 79ec6945a..e8ec512af 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -484,23 +484,23 @@ func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress util.Address) (*BlockTe tx := prioItem.tx if tx.MsgTx().SubNetworkID != wire.SubNetworkDAGCoin { - subnetwork := tx.MsgTx().SubNetworkID - gasUsage, ok := gasUsageMap[subnetwork] + subNetwork := tx.MsgTx().SubNetworkID + gasUsage, ok := gasUsageMap[subNetwork] if !ok { gasUsage = 0 } - gasLimit, err := g.dag.GasLimit(subnetwork) + gasLimit, err := g.dag.GasLimit(&subNetwork) if err != nil { - log.Errorf("Cannot get GAS limit for subnetwork %v", subnetwork) + log.Errorf("Cannot get GAS limit for subNetwork %v", subNetwork) continue } txGas := tx.MsgTx().Gas if gasLimit-gasUsage < txGas { - log.Tracef("Transaction %v (GAS=%v) ignored because gas overusage (GASUsage=%v) in subnetwork %v (GASLimit=%v)", - tx.MsgTx().TxHash, txGas, gasUsage, subnetwork, gasLimit) + log.Tracef("Transaction %v (GAS=%v) ignored because gas overusage (GASUsage=%v) in subNetwork %v (GASLimit=%v)", + tx.MsgTx().TxHash, txGas, gasUsage, subNetwork, gasLimit) continue } - gasUsageMap[subnetwork] = gasUsage + txGas + gasUsageMap[subNetwork] = gasUsage + txGas } // Enforce maximum block size. Also check for overflow. diff --git a/wire/msgtx.go b/wire/msgtx.go index 47543e06b..b5015146f 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -96,14 +96,6 @@ const ( // peers. Thus, the peak usage of the free list is 12,500 * 512 = // 6,400,000 bytes. freeListMaxItems = 12500 - - // SubNetworkReservedFirst and SubnetworkReservedLast mark the range of sub-networks that are reserved for future use - // and are currently un-assigned for anything - // SubNetworkReservedFirst is the first reserved sub-network - SubNetworkReservedFirst = 3 - - // SubNetworkUnreservedFirst is the first unreserved sub-network - SubNetworkUnreservedFirst = 256 ) var (