From 9937f66b6a7863488489fd2773137cd21b813620 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Mon, 19 Jul 2021 16:59:28 -0400 Subject: [PATCH] change.ClaimID and OutPoint types changed --- blockchain/claimtrie.go | 25 ++++----- claimtrie/change/change.go | 19 +++---- claimtrie/change/claimid.go | 51 ++++++++++++++++++ claimtrie/claimtrie.go | 30 +++++------ claimtrie/claimtrie_test.go | 38 ++++++------- claimtrie/cmd/cmd/chain.go | 20 ++----- claimtrie/cmd/cmd/ui.go | 6 +-- claimtrie/node/claim.go | 46 ++-------------- claimtrie/node/claim_list.go | 7 ++- claimtrie/node/manager_test.go | 40 +++++++------- claimtrie/node/node.go | 30 +++++------ claimtrie/node/noderepo/noderepo_test.go | 4 +- claimtrie/node/noderepo/pebble.go | 68 +++++++++++++++++++++++- claimtrie/node/normalizing_manager.go | 8 +-- 14 files changed, 229 insertions(+), 163 deletions(-) create mode 100644 claimtrie/change/claimid.go diff --git a/blockchain/claimtrie.go b/blockchain/claimtrie.go index b821c52b..32db768c 100644 --- a/blockchain/claimtrie.go +++ b/blockchain/claimtrie.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/btcsuite/btcd/claimtrie" + "github.com/btcsuite/btcd/claimtrie/change" "github.com/btcsuite/btcd/claimtrie/node" ) @@ -76,17 +77,17 @@ func (h *handler) handleTxIns(ct *claimtrie.ClaimTrie) error { return err } - var id node.ClaimID + var id change.ClaimID name := cs.Name() // name of the previous one (that we're now spending) switch cs.Opcode() { case txscript.OP_CLAIMNAME: // OP code from previous transaction - id = node.NewClaimID(op) // claimID of the previous item now being spent - h.spent[id.String()] = node.NormalizeIfNecessary(name, ct.Height()) + id = change.NewClaimID(op) // claimID of the previous item now being spent + h.spent[id.Key()] = node.NormalizeIfNecessary(name, ct.Height()) err = ct.SpendClaim(name, op, id) case txscript.OP_UPDATECLAIM: copy(id[:], cs.ClaimID()) - h.spent[id.String()] = node.NormalizeIfNecessary(name, ct.Height()) + h.spent[id.Key()] = node.NormalizeIfNecessary(name, ct.Height()) err = ct.SpendClaim(name, op, id) case txscript.OP_SUPPORTCLAIM: copy(id[:], cs.ClaimID()) @@ -101,7 +102,7 @@ func (h *handler) handleTxIns(ct *claimtrie.ClaimTrie) error { func (h *handler) handleTxOuts(ct *claimtrie.ClaimTrie) error { for i, txOut := range h.tx.MsgTx().TxOut { - op := wire.NewOutPoint(h.tx.Hash(), uint32(i)) + op := *wire.NewOutPoint(h.tx.Hash(), uint32(i)) cs, err := txscript.DecodeClaimScript(txOut.PkScript) if err == txscript.ErrNotClaimScript { continue @@ -110,31 +111,31 @@ func (h *handler) handleTxOuts(ct *claimtrie.ClaimTrie) error { return err } - var id node.ClaimID + var id change.ClaimID name := cs.Name() amt := txOut.Value value := cs.Value() switch cs.Opcode() { case txscript.OP_CLAIMNAME: - id = node.NewClaimID(*op) - err = ct.AddClaim(name, *op, id, amt, value) + id = change.NewClaimID(op) + err = ct.AddClaim(name, op, id, amt, value) case txscript.OP_SUPPORTCLAIM: copy(id[:], cs.ClaimID()) - err = ct.AddSupport(name, value, *op, amt, id) + err = ct.AddSupport(name, value, op, amt, id) case txscript.OP_UPDATECLAIM: // old code wouldn't run the update if name or claimID didn't match existing data // that was a safety feature, but it should have rejected the transaction instead // TODO: reject transactions with invalid update commands copy(id[:], cs.ClaimID()) normName := node.NormalizeIfNecessary(name, ct.Height()) - if !bytes.Equal(h.spent[id.String()], normName) { + if !bytes.Equal(h.spent[id.Key()], normName) { fmt.Printf("Invalid update operation: name or ID mismatch for %s, %s\n", normName, id.String()) continue } - delete(h.spent, id.String()) - err = ct.UpdateClaim(name, *op, amt, id, value) + delete(h.spent, id.Key()) + err = ct.UpdateClaim(name, op, amt, id, value) } if err != nil { return errors.Wrapf(err, "handleTxOuts") diff --git a/claimtrie/change/change.go b/claimtrie/change/change.go index cfce9982..2b7bc304 100644 --- a/claimtrie/change/change.go +++ b/claimtrie/change/change.go @@ -1,5 +1,7 @@ package change +import "github.com/btcsuite/btcd/wire" + type ChangeType int const ( @@ -15,8 +17,8 @@ type Change struct { Height int32 Name []byte - ClaimID string // TODO: can we store this and OutPoint as bytes? - OutPoint string + ClaimID ClaimID + OutPoint wire.OutPoint Amount int64 Value []byte @@ -26,7 +28,7 @@ type Change struct { SpentChildren map[string]bool } -func New(typ ChangeType) Change { +func NewChange(typ ChangeType) Change { return Change{Type: typ} } @@ -36,17 +38,12 @@ func (c Change) SetHeight(height int32) Change { } func (c Change) SetName(name []byte) Change { - c.Name = name + c.Name = name // need to clone it? return c } -func (c Change) SetClaimID(claimID string) Change { - c.ClaimID = claimID - return c -} - -func (c Change) SetOutPoint(op string) Change { - c.OutPoint = op +func (c Change) SetOutPoint(op *wire.OutPoint) Change { + c.OutPoint = *op return c } diff --git a/claimtrie/change/claimid.go b/claimtrie/change/claimid.go new file mode 100644 index 00000000..8b8e4c7e --- /dev/null +++ b/claimtrie/change/claimid.go @@ -0,0 +1,51 @@ +package change + +import ( + "encoding/binary" + "encoding/hex" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" +) + +// ClaimID represents a Claim's ClaimID. +type ClaimID [20]byte + +// NewClaimID returns a Claim ID calculated from Ripemd160(Sha256(OUTPOINT). +func NewClaimID(op wire.OutPoint) (id ClaimID) { + + var buffer [chainhash.HashSize + 4]byte // hoping for stack alloc + copy(buffer[:], op.Hash[:]) + binary.BigEndian.PutUint32(buffer[chainhash.HashSize:], op.Index) + copy(id[:], btcutil.Hash160(buffer[:])) + return id +} + +// NewIDFromString returns a Claim ID from a string. +func NewIDFromString(s string) (id ClaimID, err error) { + + if len(s) == 40 { + _, err = hex.Decode(id[:], []byte(s)) + } else { + copy(id[:], s) + } + for i, j := 0, len(id)-1; i < j; i, j = i+1, j-1 { + id[i], id[j] = id[j], id[i] + } + return id, err +} + +// Key is for in-memory maps +func (id ClaimID) Key() string { + return string(id[:]) +} + +// String is for anything written to a DB +func (id ClaimID) String() string { + + for i, j := 0, len(id)-1; i < j; i, j = i+1, j-1 { + id[i], id[j] = id[j], id[i] + } + + return hex.EncodeToString(id[:]) +} diff --git a/claimtrie/claimtrie.go b/claimtrie/claimtrie.go index 5b6487a3..aaa835b3 100644 --- a/claimtrie/claimtrie.go +++ b/claimtrie/claimtrie.go @@ -161,14 +161,14 @@ func New(cfg config.Config) (*ClaimTrie, error) { } // AddClaim adds a Claim to the ClaimTrie. -func (ct *ClaimTrie) AddClaim(name []byte, op wire.OutPoint, id node.ClaimID, amt int64, val []byte) error { +func (ct *ClaimTrie) AddClaim(name []byte, op wire.OutPoint, id change.ClaimID, amt int64, val []byte) error { chg := change.Change{ Type: change.AddClaim, Name: name, - OutPoint: op.String(), + OutPoint: op, Amount: amt, - ClaimID: id.String(), + ClaimID: id, Value: val, } @@ -176,14 +176,14 @@ func (ct *ClaimTrie) AddClaim(name []byte, op wire.OutPoint, id node.ClaimID, am } // UpdateClaim updates a Claim in the ClaimTrie. -func (ct *ClaimTrie) UpdateClaim(name []byte, op wire.OutPoint, amt int64, id node.ClaimID, val []byte) error { +func (ct *ClaimTrie) UpdateClaim(name []byte, op wire.OutPoint, amt int64, id change.ClaimID, val []byte) error { chg := change.Change{ Type: change.UpdateClaim, Name: name, - OutPoint: op.String(), + OutPoint: op, Amount: amt, - ClaimID: id.String(), + ClaimID: id, Value: val, } @@ -191,27 +191,27 @@ func (ct *ClaimTrie) UpdateClaim(name []byte, op wire.OutPoint, amt int64, id no } // SpendClaim spends a Claim in the ClaimTrie. -func (ct *ClaimTrie) SpendClaim(name []byte, op wire.OutPoint, id node.ClaimID) error { +func (ct *ClaimTrie) SpendClaim(name []byte, op wire.OutPoint, id change.ClaimID) error { chg := change.Change{ Type: change.SpendClaim, Name: name, - OutPoint: op.String(), - ClaimID: id.String(), + OutPoint: op, + ClaimID: id, } return ct.forwardNodeChange(chg) } // AddSupport adds a Support to the ClaimTrie. -func (ct *ClaimTrie) AddSupport(name []byte, value []byte, op wire.OutPoint, amt int64, id node.ClaimID) error { +func (ct *ClaimTrie) AddSupport(name []byte, value []byte, op wire.OutPoint, amt int64, id change.ClaimID) error { chg := change.Change{ Type: change.AddSupport, Name: name, - OutPoint: op.String(), + OutPoint: op, Amount: amt, - ClaimID: id.String(), + ClaimID: id, Value: value, } @@ -219,13 +219,13 @@ func (ct *ClaimTrie) AddSupport(name []byte, value []byte, op wire.OutPoint, amt } // SpendSupport spends a Support in the ClaimTrie. -func (ct *ClaimTrie) SpendSupport(name []byte, op wire.OutPoint, id node.ClaimID) error { +func (ct *ClaimTrie) SpendSupport(name []byte, op wire.OutPoint, id change.ClaimID) error { chg := change.Change{ Type: change.SpendSupport, Name: name, - OutPoint: op.String(), - ClaimID: id.String(), + OutPoint: op, + ClaimID: id, } return ct.forwardNodeChange(chg) diff --git a/claimtrie/claimtrie_test.go b/claimtrie/claimtrie_test.go index 4c1d6dba..7489f81a 100644 --- a/claimtrie/claimtrie_test.go +++ b/claimtrie/claimtrie_test.go @@ -3,9 +3,9 @@ package claimtrie import ( "testing" + "github.com/btcsuite/btcd/claimtrie/change" "github.com/btcsuite/btcd/claimtrie/config" "github.com/btcsuite/btcd/claimtrie/merkletrie" - "github.com/btcsuite/btcd/claimtrie/node" "github.com/btcsuite/btcd/claimtrie/param" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -52,16 +52,16 @@ func TestFixedHashes(t *testing.T) { tx3 := buildTx(tx2.TxHash()) tx4 := buildTx(tx3.TxHash()) - err = ct.AddClaim(b("test"), tx1.TxIn[0].PreviousOutPoint, node.NewClaimID(tx1.TxIn[0].PreviousOutPoint), 50, nil) + err = ct.AddClaim(b("test"), tx1.TxIn[0].PreviousOutPoint, change.NewClaimID(tx1.TxIn[0].PreviousOutPoint), 50, nil) r.NoError(err) - err = ct.AddClaim(b("test2"), tx2.TxIn[0].PreviousOutPoint, node.NewClaimID(tx2.TxIn[0].PreviousOutPoint), 50, nil) + err = ct.AddClaim(b("test2"), tx2.TxIn[0].PreviousOutPoint, change.NewClaimID(tx2.TxIn[0].PreviousOutPoint), 50, nil) r.NoError(err) - err = ct.AddClaim(b("test"), tx3.TxIn[0].PreviousOutPoint, node.NewClaimID(tx3.TxIn[0].PreviousOutPoint), 50, nil) + err = ct.AddClaim(b("test"), tx3.TxIn[0].PreviousOutPoint, change.NewClaimID(tx3.TxIn[0].PreviousOutPoint), 50, nil) r.NoError(err) - err = ct.AddClaim(b("tes"), tx4.TxIn[0].PreviousOutPoint, node.NewClaimID(tx4.TxIn[0].PreviousOutPoint), 50, nil) + err = ct.AddClaim(b("tes"), tx4.TxIn[0].PreviousOutPoint, change.NewClaimID(tx4.TxIn[0].PreviousOutPoint), 50, nil) r.NoError(err) err = ct.AppendBlock() @@ -89,27 +89,27 @@ func TestNormalizationFork(t *testing.T) { hash := chainhash.HashH([]byte{1, 2, 3}) o1 := wire.OutPoint{Hash: hash, Index: 1} - err = ct.AddClaim([]byte("AÑEJO"), o1, node.NewClaimID(o1), 10, nil) + err = ct.AddClaim([]byte("AÑEJO"), o1, change.NewClaimID(o1), 10, nil) r.NoError(err) o2 := wire.OutPoint{Hash: hash, Index: 2} - err = ct.AddClaim([]byte("AÑejo"), o2, node.NewClaimID(o2), 5, nil) + err = ct.AddClaim([]byte("AÑejo"), o2, change.NewClaimID(o2), 5, nil) r.NoError(err) o3 := wire.OutPoint{Hash: hash, Index: 3} - err = ct.AddClaim([]byte("あてはまる"), o3, node.NewClaimID(o3), 5, nil) + err = ct.AddClaim([]byte("あてはまる"), o3, change.NewClaimID(o3), 5, nil) r.NoError(err) o4 := wire.OutPoint{Hash: hash, Index: 4} - err = ct.AddClaim([]byte("Aḿlie"), o4, node.NewClaimID(o4), 5, nil) + err = ct.AddClaim([]byte("Aḿlie"), o4, change.NewClaimID(o4), 5, nil) r.NoError(err) o5 := wire.OutPoint{Hash: hash, Index: 5} - err = ct.AddClaim([]byte("TEST"), o5, node.NewClaimID(o5), 5, nil) + err = ct.AddClaim([]byte("TEST"), o5, change.NewClaimID(o5), 5, nil) r.NoError(err) o6 := wire.OutPoint{Hash: hash, Index: 6} - err = ct.AddClaim([]byte("test"), o6, node.NewClaimID(o6), 7, nil) + err = ct.AddClaim([]byte("test"), o6, change.NewClaimID(o6), 7, nil) r.NoError(err) err = ct.AppendBlock() @@ -122,7 +122,7 @@ func TestNormalizationFork(t *testing.T) { r.Equal(int32(1), n.TakenOverAt) o7 := wire.OutPoint{Hash: hash, Index: 7} - err = ct.AddClaim([]byte("aÑEJO"), o7, node.NewClaimID(o7), 8, nil) + err = ct.AddClaim([]byte("aÑEJO"), o7, change.NewClaimID(o7), 8, nil) r.NoError(err) err = ct.AppendBlock() @@ -153,7 +153,7 @@ func TestActivationsOnNormalizationFork(t *testing.T) { hash := chainhash.HashH([]byte{1, 2, 3}) o7 := wire.OutPoint{Hash: hash, Index: 7} - err = ct.AddClaim([]byte("A"), o7, node.NewClaimID(o7), 1, nil) + err = ct.AddClaim([]byte("A"), o7, change.NewClaimID(o7), 1, nil) r.NoError(err) err = ct.AppendBlock() r.NoError(err) @@ -164,7 +164,7 @@ func TestActivationsOnNormalizationFork(t *testing.T) { verifyBestIndex(t, ct, "A", 7, 1) o8 := wire.OutPoint{Hash: hash, Index: 8} - err = ct.AddClaim([]byte("A"), o8, node.NewClaimID(o8), 2, nil) + err = ct.AddClaim([]byte("A"), o8, change.NewClaimID(o8), 2, nil) r.NoError(err) err = ct.AppendBlock() r.NoError(err) @@ -199,15 +199,15 @@ func TestNormalizationSortOrder(t *testing.T) { hash := chainhash.HashH([]byte{1, 2, 3}) o1 := wire.OutPoint{Hash: hash, Index: 1} - err = ct.AddClaim([]byte("A"), o1, node.NewClaimID(o1), 1, nil) + err = ct.AddClaim([]byte("A"), o1, change.NewClaimID(o1), 1, nil) r.NoError(err) o2 := wire.OutPoint{Hash: hash, Index: 2} - err = ct.AddClaim([]byte("A"), o2, node.NewClaimID(o2), 2, nil) + err = ct.AddClaim([]byte("A"), o2, change.NewClaimID(o2), 2, nil) r.NoError(err) o3 := wire.OutPoint{Hash: hash, Index: 3} - err = ct.AddClaim([]byte("a"), o3, node.NewClaimID(o3), 3, nil) + err = ct.AddClaim([]byte("a"), o3, change.NewClaimID(o3), 3, nil) r.NoError(err) err = ct.AppendBlock() @@ -246,11 +246,11 @@ func TestRebuild(t *testing.T) { hash := chainhash.HashH([]byte{1, 2, 3}) o1 := wire.OutPoint{Hash: hash, Index: 1} - err = ct.AddClaim([]byte("test1"), o1, node.NewClaimID(o1), 1, nil) + err = ct.AddClaim([]byte("test1"), o1, change.NewClaimID(o1), 1, nil) r.NoError(err) o2 := wire.OutPoint{Hash: hash, Index: 2} - err = ct.AddClaim([]byte("test2"), o2, node.NewClaimID(o2), 2, nil) + err = ct.AddClaim([]byte("test2"), o2, change.NewClaimID(o2), 2, nil) r.NoError(err) err = ct.AppendBlock() diff --git a/claimtrie/cmd/cmd/chain.go b/claimtrie/cmd/cmd/chain.go index 7609e422..ef6bc597 100644 --- a/claimtrie/cmd/cmd/chain.go +++ b/claimtrie/cmd/cmd/chain.go @@ -13,8 +13,6 @@ import ( "github.com/btcsuite/btcd/claimtrie/chain/chainrepo" "github.com/btcsuite/btcd/claimtrie/change" "github.com/btcsuite/btcd/claimtrie/config" - "github.com/btcsuite/btcd/claimtrie/node" - "github.com/cockroachdb/pebble" "github.com/spf13/cobra" ) @@ -134,30 +132,22 @@ var chainReplayCmd = &cobra.Command{ } for _, chg := range changes { - claimID, _ := node.NewIDFromString(chg.ClaimID) switch chg.Type { case change.AddClaim: - op := *node.NewOutPointFromString(chg.OutPoint) - err = ct.AddClaim(chg.Name, op, claimID, chg.Amount, chg.Value) + err = ct.AddClaim(chg.Name, chg.OutPoint, chg.ClaimID, chg.Amount, chg.Value) case change.UpdateClaim: - op := *node.NewOutPointFromString(chg.OutPoint) - err = ct.UpdateClaim(chg.Name, op, chg.Amount, claimID, chg.Value) + err = ct.UpdateClaim(chg.Name, chg.OutPoint, chg.Amount, chg.ClaimID, chg.Value) case change.SpendClaim: - op := *node.NewOutPointFromString(chg.OutPoint) - err = ct.SpendClaim(chg.Name, op, claimID) + err = ct.SpendClaim(chg.Name, chg.OutPoint, chg.ClaimID) case change.AddSupport: - op := *node.NewOutPointFromString(chg.OutPoint) - claimID, _ := node.NewIDFromString(chg.ClaimID) - id := claimID - err = ct.AddSupport(chg.Name, chg.Value, op, chg.Amount, id) + err = ct.AddSupport(chg.Name, chg.Value, chg.OutPoint, chg.Amount, chg.ClaimID) case change.SpendSupport: - op := *node.NewOutPointFromString(chg.OutPoint) - err = ct.SpendSupport(chg.Name, op, claimID) + err = ct.SpendSupport(chg.Name, chg.OutPoint, chg.ClaimID) default: err = fmt.Errorf("invalid change: %v", chg) diff --git a/claimtrie/cmd/cmd/ui.go b/claimtrie/cmd/cmd/ui.go index 6bb78c02..2f9f7162 100644 --- a/claimtrie/cmd/cmd/ui.go +++ b/claimtrie/cmd/cmd/ui.go @@ -32,7 +32,7 @@ func changeName(c change.ChangeType) string { func showChange(chg change.Change) { fmt.Printf(">>> Height: %6d: %s for %04s, %d, %s\n", - chg.Height, changeName(chg.Type), chg.ClaimID, chg.Amount, chg.OutPoint) + chg.Height, changeName(chg.Type), chg.ClaimID.String(), chg.Amount, chg.OutPoint) } func showClaim(c *node.Claim, n *node.Node) { @@ -42,12 +42,12 @@ func showClaim(c *node.Claim, n *node.Node) { } fmt.Printf("%s C ID: %s, TXO: %s\n %5d/%-5d, Status: %9s, Amount: %15d, Support Amount: %15d\n", - mark, c.ClaimID, c.OutPoint, c.AcceptedAt, c.ActiveAt, status[c.Status], c.Amount, n.SupportSums[c.ClaimID]) + mark, c.ClaimID.String(), c.OutPoint, c.AcceptedAt, c.ActiveAt, status[c.Status], c.Amount, n.SupportSums[c.ClaimID.Key()]) } func showSupport(c *node.Claim) { fmt.Printf(" S id: %s, op: %s, %5d/%-5d, %9s, amt: %15d\n", - c.ClaimID, c.OutPoint, c.AcceptedAt, c.ActiveAt, status[c.Status], c.Amount) + c.ClaimID.String(), c.OutPoint, c.AcceptedAt, c.ActiveAt, status[c.Status], c.Amount) } func showNode(n *node.Node) { diff --git a/claimtrie/node/claim.go b/claimtrie/node/claim.go index eabdbd57..0cc3fbed 100644 --- a/claimtrie/node/claim.go +++ b/claimtrie/node/claim.go @@ -2,55 +2,15 @@ package node import ( "bytes" - "encoding/binary" - "encoding/hex" "strconv" "strings" - "github.com/btcsuite/btcd/claimtrie/param" - "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/claimtrie/change" + "github.com/btcsuite/btcd/claimtrie/param" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" ) -// ClaimID represents a Claim's ClaimID. -type ClaimID [20]byte - -// NewClaimID returns a Claim ID calculated from Ripemd160(Sha256(OUTPOINT). -func NewClaimID(op wire.OutPoint) ClaimID { - - w := bytes.NewBuffer(op.Hash[:]) - if err := binary.Write(w, binary.BigEndian, op.Index); err != nil { - panic(err) - } - var id ClaimID - copy(id[:], btcutil.Hash160(w.Bytes())) - - return id -} - -// NewIDFromString returns a Claim ID from a string. -func NewIDFromString(s string) (ClaimID, error) { - - var id ClaimID - _, err := hex.Decode(id[:], []byte(s)) - for i, j := 0, len(id)-1; i < j; i, j = i+1, j-1 { - id[i], id[j] = id[j], id[i] - } - - return id, err -} - -func (id ClaimID) String() string { - - for i, j := 0, len(id)-1; i < j; i, j = i+1, j-1 { - id[i], id[j] = id[j], id[i] - } - - return hex.EncodeToString(id[:]) -} - type Status int const ( @@ -62,7 +22,7 @@ const ( // Claim defines a structure of stake, which could be a Claim or Support. type Claim struct { OutPoint wire.OutPoint - ClaimID string + ClaimID change.ClaimID Amount int64 AcceptedAt int32 // when arrived (aka, originally landed in block) ActiveAt int32 // AcceptedAt + actual delay diff --git a/claimtrie/node/claim_list.go b/claimtrie/node/claim_list.go index df8957d6..d1f863da 100644 --- a/claimtrie/node/claim_list.go +++ b/claimtrie/node/claim_list.go @@ -1,12 +1,15 @@ package node -import "github.com/btcsuite/btcd/wire" +import ( + "github.com/btcsuite/btcd/claimtrie/change" + "github.com/btcsuite/btcd/wire" +) type ClaimList []*Claim type comparator func(c *Claim) bool -func byID(id string) comparator { +func byID(id change.ClaimID) comparator { return func(c *Claim) bool { return c.ClaimID == id } diff --git a/claimtrie/node/manager_test.go b/claimtrie/node/manager_test.go index 086fc223..5fc7f08e 100644 --- a/claimtrie/node/manager_test.go +++ b/claimtrie/node/manager_test.go @@ -57,13 +57,13 @@ func TestSimpleAddClaim(t *testing.T) { _, err = m.IncrementHeightTo(10) r.NoError(err) - chg := change.New(change.AddClaim).SetName(name1).SetOutPoint(out1.String()).SetHeight(11) + chg := change.NewChange(change.AddClaim).SetName(name1).SetOutPoint(out1).SetHeight(11) err = m.AppendChange(chg) r.NoError(err) _, err = m.IncrementHeightTo(11) r.NoError(err) - chg = chg.SetName(name2).SetOutPoint(out2.String()).SetHeight(12) + chg = chg.SetName(name2).SetOutPoint(out2).SetHeight(12) err = m.AppendChange(chg) r.NoError(err) _, err = m.IncrementHeightTo(12) @@ -107,31 +107,31 @@ func TestSupportAmounts(t *testing.T) { _, err = m.IncrementHeightTo(10) r.NoError(err) - chg := change.New(change.AddClaim).SetName(name1).SetOutPoint(out1.String()).SetHeight(11).SetAmount(3) - chg.ClaimID = NewClaimID(*out1).String() + chg := change.NewChange(change.AddClaim).SetName(name1).SetOutPoint(out1).SetHeight(11).SetAmount(3) + chg.ClaimID = change.NewClaimID(*out1) err = m.AppendChange(chg) r.NoError(err) - chg = change.New(change.AddClaim).SetName(name1).SetOutPoint(out2.String()).SetHeight(11).SetAmount(4) - chg.ClaimID = NewClaimID(*out2).String() + chg = change.NewChange(change.AddClaim).SetName(name1).SetOutPoint(out2).SetHeight(11).SetAmount(4) + chg.ClaimID = change.NewClaimID(*out2) err = m.AppendChange(chg) r.NoError(err) _, err = m.IncrementHeightTo(11) r.NoError(err) - chg = change.New(change.AddSupport).SetName(name1).SetOutPoint(out3.String()).SetHeight(12).SetAmount(2) - chg.ClaimID = NewClaimID(*out1).String() + chg = change.NewChange(change.AddSupport).SetName(name1).SetOutPoint(out3).SetHeight(12).SetAmount(2) + chg.ClaimID = change.NewClaimID(*out1) err = m.AppendChange(chg) r.NoError(err) - chg = change.New(change.AddSupport).SetName(name1).SetOutPoint(out4.String()).SetHeight(12).SetAmount(2) - chg.ClaimID = NewClaimID(*out2).String() + chg = change.NewChange(change.AddSupport).SetName(name1).SetOutPoint(out4).SetHeight(12).SetAmount(2) + chg.ClaimID = change.NewClaimID(*out2) err = m.AppendChange(chg) r.NoError(err) - chg = change.New(change.SpendSupport).SetName(name1).SetOutPoint(out4.String()).SetHeight(12).SetAmount(2) - chg.ClaimID = NewClaimID(*out2).String() + chg = change.NewChange(change.SpendSupport).SetName(name1).SetOutPoint(out4).SetHeight(12).SetAmount(2) + chg.ClaimID = change.NewClaimID(*out2) err = m.AppendChange(chg) r.NoError(err) @@ -141,7 +141,7 @@ func TestSupportAmounts(t *testing.T) { n1, err := m.Node(name1) r.NoError(err) r.Equal(2, len(n1.Claims)) - r.Equal(int64(5), n1.BestClaim.Amount+n1.SupportSums[n1.BestClaim.ClaimID]) + r.Equal(int64(5), n1.BestClaim.Amount+n1.SupportSums[n1.BestClaim.ClaimID.Key()]) } func TestNodeSort(t *testing.T) { @@ -154,14 +154,14 @@ func TestNodeSort(t *testing.T) { r.True(OutPointLess(*out1, *out3)) n := New() - n.Claims = append(n.Claims, &Claim{OutPoint: *out1, AcceptedAt: 3, Amount: 3, ClaimID: "a"}) - n.Claims = append(n.Claims, &Claim{OutPoint: *out2, AcceptedAt: 3, Amount: 3, ClaimID: "b"}) + n.Claims = append(n.Claims, &Claim{OutPoint: *out1, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{1}}) + n.Claims = append(n.Claims, &Claim{OutPoint: *out2, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{2}}) n.handleExpiredAndActivated(3) n.updateTakeoverHeight(3, []byte{}, true) r.Equal(n.Claims.find(byOut(*out1)).OutPoint.String(), n.BestClaim.OutPoint.String()) - n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 3, Amount: 3, ClaimID: "c"}) + n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{3}}) n.handleExpiredAndActivated(3) n.updateTakeoverHeight(3, []byte{}, true) r.Equal(n.Claims.find(byOut(*out1)).OutPoint.String(), n.BestClaim.OutPoint.String()) @@ -174,10 +174,10 @@ func TestClaimSort(t *testing.T) { param.ExtendedClaimExpirationTime = 1000 n := New() - n.Claims = append(n.Claims, &Claim{OutPoint: *out2, AcceptedAt: 3, Amount: 3, ClaimID: "b"}) - n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 3, Amount: 2, ClaimID: "c"}) - n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 4, Amount: 2, ClaimID: "d"}) - n.Claims = append(n.Claims, &Claim{OutPoint: *out1, AcceptedAt: 3, Amount: 4, ClaimID: "a"}) + n.Claims = append(n.Claims, &Claim{OutPoint: *out2, AcceptedAt: 3, Amount: 3, ClaimID: change.ClaimID{2}}) + n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 3, Amount: 2, ClaimID: change.ClaimID{3}}) + n.Claims = append(n.Claims, &Claim{OutPoint: *out3, AcceptedAt: 4, Amount: 2, ClaimID: change.ClaimID{4}}) + n.Claims = append(n.Claims, &Claim{OutPoint: *out1, AcceptedAt: 3, Amount: 4, ClaimID: change.ClaimID{1}}) n.SortClaims() r.Equal(int64(4), n.Claims[0].Amount) diff --git a/claimtrie/node/node.go b/claimtrie/node/node.go index c8859995..2d544137 100644 --- a/claimtrie/node/node.go +++ b/claimtrie/node/node.go @@ -31,8 +31,6 @@ func (n *Node) HasActiveBestClaim() bool { func (n *Node) ApplyChange(chg change.Change, delay int32) error { - out := NewOutPointFromString(chg.OutPoint) - visibleAt := chg.VisibleHeight if visibleAt <= 0 { visibleAt = chg.Height @@ -41,7 +39,7 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { switch chg.Type { case change.AddClaim: c := &Claim{ - OutPoint: *out, + OutPoint: chg.OutPoint, Amount: chg.Amount, ClaimID: chg.ClaimID, AcceptedAt: chg.Height, // not tracking original height in this version (but we could) @@ -49,14 +47,14 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { Value: chg.Value, VisibleAt: visibleAt, } - old := n.Claims.find(byOut(*out)) // TODO: remove this after proving ResetHeight works + old := n.Claims.find(byOut(chg.OutPoint)) // TODO: remove this after proving ResetHeight works if old != nil { fmt.Printf("CONFLICT WITH EXISTING TXO! Name: %s, Height: %d\n", chg.Name, chg.Height) } n.Claims = append(n.Claims, c) case change.SpendClaim: - c := n.Claims.find(byOut(*out)) + c := n.Claims.find(byOut(chg.OutPoint)) if c != nil { c.setStatus(Deactivated) } else if !mispents[fmt.Sprintf("%d_%s", chg.Height, chg.ClaimID)] { @@ -74,7 +72,7 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { // Keep its ID, which was generated from the spent claim. // And update the rest of properties. - c.setOutPoint(*out).SetAmt(chg.Amount).SetValue(chg.Value) + c.setOutPoint(chg.OutPoint).SetAmt(chg.Amount).SetValue(chg.Value) c.setStatus(Accepted) // it was Deactivated in the spend (but we only activate at the end of the block) // that's because the old code would put all insertions into the "queue" that was processed at block's end @@ -88,7 +86,7 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { } case change.AddSupport: n.Supports = append(n.Supports, &Claim{ - OutPoint: *out, + OutPoint: chg.OutPoint, Amount: chg.Amount, ClaimID: chg.ClaimID, AcceptedAt: chg.Height, @@ -98,10 +96,10 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error { }) case change.SpendSupport: - s := n.Supports.find(byOut(*out)) + s := n.Supports.find(byOut(chg.OutPoint)) if s != nil { if s.Status == Activated { - n.SupportSums[s.ClaimID] -= s.Amount + n.SupportSums[s.ClaimID.Key()] -= s.Amount } // TODO: we could do without this Deactivated flag if we set expiration instead // That would eliminate the above Sum update. @@ -170,7 +168,7 @@ func (n *Node) handleExpiredAndActivated(height int32) int { c.setStatus(Activated) changes++ if sums != nil { - sums[c.ClaimID] += c.Amount + sums[c.ClaimID.Key()] += c.Amount } } if c.ExpireAt() <= height || c.Status == Deactivated { @@ -181,7 +179,7 @@ func (n *Node) handleExpiredAndActivated(height int32) int { items = items[:len(items)-1] changes++ if sums != nil && c.Status != Deactivated { - sums[c.ClaimID] -= c.Amount + sums[c.ClaimID.Key()] -= c.Amount } } } @@ -252,9 +250,9 @@ func (n Node) findBestClaim() *Claim { continue } - candidateAmount := candidate.Amount + n.SupportSums[candidate.ClaimID] + candidateAmount := candidate.Amount + n.SupportSums[candidate.ClaimID.Key()] if bestAmount <= 0 { - bestAmount = best.Amount + n.SupportSums[best.ClaimID] + bestAmount = best.Amount + n.SupportSums[best.ClaimID.Key()] } switch { @@ -292,7 +290,7 @@ func (n *Node) activateAllClaims(height int32) int { s.setActiveAt(height) // don't necessarily need to change this number? s.setStatus(Activated) count++ - n.SupportSums[s.ClaimID] += s.Amount + n.SupportSums[s.ClaimID.Key()] += s.Amount } } return count @@ -302,8 +300,8 @@ func (n *Node) SortClaims() { // purposefully sorting by descent sort.Slice(n.Claims, func(j, i int) bool { - iAmount := n.Claims[i].Amount + n.SupportSums[n.Claims[i].ClaimID] - jAmount := n.Claims[j].Amount + n.SupportSums[n.Claims[j].ClaimID] + iAmount := n.Claims[i].Amount + n.SupportSums[n.Claims[i].ClaimID.Key()] + jAmount := n.Claims[j].Amount + n.SupportSums[n.Claims[j].ClaimID.Key()] switch { case iAmount < jAmount: return true diff --git a/claimtrie/node/noderepo/noderepo_test.go b/claimtrie/node/noderepo/noderepo_test.go index 20dc0ea9..1cf2e64e 100644 --- a/claimtrie/node/noderepo/noderepo_test.go +++ b/claimtrie/node/noderepo/noderepo_test.go @@ -10,7 +10,7 @@ import ( ) var ( - opStr1 = "0000000000000000000000000000000000000000000000000000000000000000:1" + out1 = node.NewOutPointFromString("0000000000000000000000000000000000000000000000000000000000000000:1") testNodeName1 = []byte("name1") ) @@ -39,7 +39,7 @@ func testNodeRepo(t *testing.T, repo node.Repo, setup, cleanup func()) { r := require.New(t) - chg := change.New(change.AddClaim).SetName(testNodeName1).SetOutPoint(opStr1) + chg := change.NewChange(change.AddClaim).SetName(testNodeName1).SetOutPoint(out1) testcases := []struct { name string diff --git a/claimtrie/node/noderepo/pebble.go b/claimtrie/node/noderepo/pebble.go index 06dc326d..d4611c4d 100644 --- a/claimtrie/node/noderepo/pebble.go +++ b/claimtrie/node/noderepo/pebble.go @@ -3,16 +3,82 @@ package noderepo import ( "bytes" "fmt" + "reflect" + "sort" + + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/claimtrie/change" + "github.com/btcsuite/btcd/claimtrie/node" + "github.com/btcsuite/btcd/wire" + "github.com/cockroachdb/pebble" "github.com/vmihailenco/msgpack/v5" - "sort" ) type Pebble struct { db *pebble.DB } +func init() { + claimEncoder := func(e *msgpack.Encoder, v reflect.Value) error { + claim := v.Interface().(change.ClaimID) + return e.EncodeBytes(claim[:]) + } + claimDecoder := func(e *msgpack.Decoder, v reflect.Value) error { + data, err := e.DecodeBytes() + if err != nil { + s, err := e.DecodeString() + if err != nil { + return err + } + id, err := change.NewIDFromString(s) + if err != nil { + return err + } + v.Set(reflect.ValueOf(id)) + } else { + id := change.ClaimID{} + copy(id[:], data) + v.Set(reflect.ValueOf(id)) + } + return nil + } + msgpack.Register(change.ClaimID{}, claimEncoder, claimDecoder) + + opEncoder := func(e *msgpack.Encoder, v reflect.Value) error { + op := v.Interface().(wire.OutPoint) + if err := e.EncodeBytes(op.Hash[:]); err != nil { + return err + } + return e.EncodeUint32(op.Index) + } + opDecoder := func(e *msgpack.Decoder, v reflect.Value) error { + data, err := e.DecodeBytes() + if err != nil { + // try the older data: + s, err := e.DecodeString() + if err != nil { + return err + } + op := node.NewOutPointFromString(s) + v.Set(reflect.ValueOf(op)) + } else { + index, err := e.DecodeUint32() + if err != nil { + return err + } + hash, err := chainhash.NewHash(data) + if err != nil { + return err + } + op := wire.NewOutPoint(hash, index) + v.Set(reflect.ValueOf(*op)) + } + return nil + } + msgpack.Register(wire.OutPoint{}, opEncoder, opDecoder) +} + func NewPebble(path string) (*Pebble, error) { db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(256 << 20), BytesPerSync: 16 << 20}) diff --git a/claimtrie/node/normalizing_manager.go b/claimtrie/node/normalizing_manager.go index 684af397..b030320b 100644 --- a/claimtrie/node/normalizing_manager.go +++ b/claimtrie/node/normalizing_manager.go @@ -83,7 +83,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3 Type: change.AddClaim, Name: norm, Height: c.AcceptedAt, - OutPoint: c.OutPoint.String(), + OutPoint: c.OutPoint, ClaimID: c.ClaimID, Amount: c.Amount, Value: c.Value, @@ -94,7 +94,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3 Type: change.SpendClaim, Name: clone, Height: height, - OutPoint: c.OutPoint.String(), + OutPoint: c.OutPoint, }) } for _, c := range n.Supports { @@ -102,7 +102,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3 Type: change.AddSupport, Name: norm, Height: c.AcceptedAt, - OutPoint: c.OutPoint.String(), + OutPoint: c.OutPoint, ClaimID: c.ClaimID, Amount: c.Amount, Value: c.Value, @@ -113,7 +113,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3 Type: change.SpendSupport, Name: clone, Height: height, - OutPoint: c.OutPoint.String(), + OutPoint: c.OutPoint, }) }