Merge remote-tracking branch 'origin/dev-304-change-subnetworkid-to-hash-instead-of-running-number'

This commit is contained in:
Mike Zak 2019-01-10 17:23:45 +02:00
commit 1743877b66
43 changed files with 639 additions and 700 deletions

View File

@ -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)

View File

@ -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

View File

@ -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},

View File

@ -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
})
}

View File

@ -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

View File

@ -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,
},

View File

@ -4,27 +4,57 @@ import (
"bytes"
"encoding/binary"
"fmt"
"github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/util"
"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
@ -39,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 uint64) (*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 {
@ -115,217 +94,70 @@ func (dag *BlockDAG) subNetwork(subNetworkID uint64) (*subNetwork, error) {
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 uint64) (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 uint64) (*subNetwork, error) {
// Serialize the sub-network ID
subNetworkIDBytes := make([]byte, 8)
byteOrder.PutUint64(subNetworkIDBytes, subNetworkID)
// 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(subNetworkIDBytes)
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
@ -336,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
}

View File

@ -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: &params,
})
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,
}

View File

@ -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
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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")
}
}

View File

@ -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,

View File

@ -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.NewFromStr(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)

View File

@ -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")
}
}

View File

@ -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},
}

View File

@ -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, /* |..| */
}

View File

@ -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
}

Binary file not shown.

View File

@ -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
}

View File

@ -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)
}

View File

@ -15,6 +15,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"
)
@ -475,7 +476,7 @@ func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress util.Address) (*BlockTe
totalFees := uint64(0)
// Create map of GAS usage per subnetwork
gasUsageMap := make(map[uint64]uint64)
gasUsageMap := make(map[subnetworkid.SubNetworkID]uint64)
// Choose which transactions make it into the block.
for priorityQueue.Len() > 0 {
@ -485,23 +486,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.
@ -645,7 +646,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.

View File

@ -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,
},
}

View File

@ -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.",

View File

@ -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.

View File

@ -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)

View File

@ -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 {

View File

@ -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"

View File

@ -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])
})
}

View File

@ -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)

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
010000000255605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D28350000000049483045022100AA46504BAA86DF8A33B1192B1B9367B4D729DC41E389F2C04F3E5C7F0559AAE702205E82253A54BF5C4F65B7428551554B2045167D6D206DFE6A2E198127D3F7DF1501FFFFFFFFFFFFFFFF55605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D2835010000004847304402202329484C35FA9D6BB32A55A70C0982F606CE0E3634B69006138683BCD12CBB6602200C28FEB1E2555C3210F1DDDB299738B4FF8BBE9667B68CB8764B5AC17B7ADF0001FFFFFFFFFFFFFFFF0200E1F505000000004341046A0765B5865641CE08DD39690AADE26DFBF5511430CA428A3089261361CEF170E3929A68AEE3D8D4848B0C5111B0A37B82B86AD559FD2A745B44D8E8D9DFDC0CAC00180D8F000000004341044A656F065871A353F216CA26CEF8DDE2F03E8C16202D2E8AD769F02032CB86A5EB5E56842E92E19141D60A01928F8DD2C875A390F67C1F6C94CFC617C0EA45AFAC00000000000000000100000000000000
010000000255605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D28350000000049483045022100AA46504BAA86DF8A33B1192B1B9367B4D729DC41E389F2C04F3E5C7F0559AAE702205E82253A54BF5C4F65B7428551554B2045167D6D206DFE6A2E198127D3F7DF1501FFFFFFFFFFFFFFFF55605DC6F5C3DC148B6DA58442B0B2CD422BE385EAB2EBEA4119EE9C268D2835010000004847304402202329484C35FA9D6BB32A55A70C0982F606CE0E3634B69006138683BCD12CBB6602200C28FEB1E2555C3210F1DDDB299738B4FF8BBE9667B68CB8764B5AC17B7ADF0001FFFFFFFFFFFFFFFF0200E1F505000000004341046A0765B5865641CE08DD39690AADE26DFBF5511430CA428A3089261361CEF170E3929A68AEE3D8D4848B0C5111B0A37B82B86AD559FD2A745B44D8E8D9DFDC0CAC00180D8F000000004341044A656F065871A353F216CA26CEF8DDE2F03E8C16202D2E8AD769F02032CB86A5EB5E56842E92E19141D60A01928F8DD2C875A390F67C1F6C94CFC617C0EA45AFAC00000000000000000100000000000000000000000000000000000000

View File

@ -1 +1 @@
0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffffffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000000000000100000000000000
0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffffffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000000000000100000000000000000000000000000000000000

View File

@ -1 +1 @@
01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffffffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000000000000100000000000000
01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffffffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000000000000100000000000000000000000000000000000000

View File

@ -1 +1 @@
01000000011f636d0003f673b3aeea4971daef16b8eed784cf6e8019a5ae7da4985fbb06e5000000008a47304402205103941e2b11e746dfa817888d422f6e7f4d16dbbfb8ffa61d15ffb924a84b8802202fe861b0f23f17139d15a3374bfc6c7196d371f3d1a324e31cc0aadbba87e53c0141049e7e1b251a7e26cae9ee7553b278ef58ef3c28b4b20134d51b747d9b18b0a19b94b66cef320e2549dec0ea3d725cb4c742f368928b1fb74b4603e24a1e262c80ffffffffffffffff0240420f00000000001976a914bcfa0e27218a7c97257b351b03a9eac95c25a23988ac40420f00000000001976a9140c6a68f20bafc678164d171ee4f077adfa9b091688ac00000000000000000100000000000000
01000000011f636d0003f673b3aeea4971daef16b8eed784cf6e8019a5ae7da4985fbb06e5000000008a47304402205103941e2b11e746dfa817888d422f6e7f4d16dbbfb8ffa61d15ffb924a84b8802202fe861b0f23f17139d15a3374bfc6c7196d371f3d1a324e31cc0aadbba87e53c0141049e7e1b251a7e26cae9ee7553b278ef58ef3c28b4b20134d51b747d9b18b0a19b94b66cef320e2549dec0ea3d725cb4c742f368928b1fb74b4603e24a1e262c80ffffffffffffffff0240420f00000000001976a914bcfa0e27218a7c97257b351b03a9eac95c25a23988ac40420f00000000001976a9140c6a68f20bafc678164d171ee4f077adfa9b091688ac00000000000000000100000000000000000000000000000000000000

View File

@ -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",
},
}

View File

@ -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},

View File

@ -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},
}

View File

@ -13,6 +13,7 @@ import (
"strconv"
"github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/util/subnetworkid"
)
const (
@ -95,23 +96,17 @@ const (
// peers. Thus, the peak usage of the free list is 12,500 * 512 =
// 6,400,000 bytes.
freeListMaxItems = 12500
)
var (
// SubNetworkSupportsAll is the sub-network id that is used to signal to peers that you support all sub-networks
SubNetworkSupportsAll = 0
SubNetworkSupportsAll = subnetworkid.SubNetworkID{}
// SubNetworkDAGCoin is the default sub-network which is used for transactions without related payload data
SubNetworkDAGCoin = 1
SubNetworkDAGCoin = subnetworkid.SubNetworkID{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
SubNetworkReservedFirst = 3
// SubNetworkUnreservedFirst is the first unreserved sub-network
SubNetworkUnreservedFirst = 256
SubNetworkRegistry = subnetworkid.SubNetworkID{2}
)
// scriptFreeList defines a free list of byte slices (up to the maximum number
@ -264,7 +259,7 @@ type MsgTx struct {
TxIn []*TxIn
TxOut []*TxOut
LockTime uint64
SubNetworkID uint64
SubNetworkID subnetworkid.SubNetworkID
Gas uint64
Payload []byte
}
@ -463,7 +458,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 +608,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 +628,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 <nil> payload", msg.SubNetworkID)
return messageError("MsgTx.BtcEncode", str)
@ -665,10 +663,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 {

View File

@ -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