mirror of
https://github.com/LBRYFoundation/lbcd.git
synced 2025-08-23 17:47:24 +00:00
[lbry] many methods now use errors.Wrap, others use node.log
added hasChildren test
This commit is contained in:
parent
d691ab7a9e
commit
ab852a6e9f
22 changed files with 248 additions and 332 deletions
|
@ -15,10 +15,7 @@ import (
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hack: print which block mismatches happened, but keep recording.
|
func (b *BlockChain) ParseClaimScripts(block *btcutil.Block, bn *blockNode, view *UtxoViewpoint, failOnHashMiss bool) error {
|
||||||
var mismatchedPrinted bool
|
|
||||||
|
|
||||||
func (b *BlockChain) ParseClaimScripts(block *btcutil.Block, node *blockNode, view *UtxoViewpoint, failOnHashMiss bool) error {
|
|
||||||
ht := block.Height()
|
ht := block.Height()
|
||||||
|
|
||||||
for _, tx := range block.Transactions() {
|
for _, tx := range block.Transactions() {
|
||||||
|
@ -32,22 +29,22 @@ func (b *BlockChain) ParseClaimScripts(block *btcutil.Block, node *blockNode, vi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack: let the claimtrie know the expected Hash.
|
// Hack: let the claimtrie know the expected Hash.
|
||||||
b.claimTrie.ReportHash(ht, node.claimTrie)
|
err := b.claimTrie.ReportHash(ht, bn.claimTrie)
|
||||||
|
|
||||||
err := b.claimTrie.AppendBlock()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrapf(err, "in report hash")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = b.claimTrie.AppendBlock()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "in append block")
|
||||||
}
|
}
|
||||||
hash := b.claimTrie.MerkleHash()
|
hash := b.claimTrie.MerkleHash()
|
||||||
|
|
||||||
if node.claimTrie != *hash {
|
if bn.claimTrie != *hash {
|
||||||
if failOnHashMiss {
|
if failOnHashMiss {
|
||||||
return fmt.Errorf("height: %d, ct.MerkleHash: %s != node.ClaimTrie: %s", ht, *hash, node.claimTrie)
|
return errors.Errorf("height: %d, ct.MerkleHash: %s != node.ClaimTrie: %s", ht, *hash, bn.claimTrie)
|
||||||
}
|
|
||||||
if !mismatchedPrinted {
|
|
||||||
fmt.Printf("\n\nHeight: %d, ct.MerkleHash: %s != node.ClaimTrie: %s, Error: %s\n", ht, *hash, node.claimTrie, err)
|
|
||||||
mismatchedPrinted = true
|
|
||||||
}
|
}
|
||||||
|
node.LogOnce(fmt.Sprintf("\n\nHeight: %d, ct.MerkleHash: %s != node.ClaimTrie: %s, Error: %s", ht, *hash, bn.claimTrie, err))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -67,7 +64,7 @@ func (h *handler) handleTxIns(ct *claimtrie.ClaimTrie) error {
|
||||||
op := txIn.PreviousOutPoint
|
op := txIn.PreviousOutPoint
|
||||||
e := h.view.LookupEntry(op)
|
e := h.view.LookupEntry(op)
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return fmt.Errorf("missing input in view for %s", op.String())
|
return errors.Errorf("missing input in view for %s", op.String())
|
||||||
}
|
}
|
||||||
cs, err := txscript.DecodeClaimScript(e.pkScript)
|
cs, err := txscript.DecodeClaimScript(e.pkScript)
|
||||||
if err == txscript.ErrNotClaimScript {
|
if err == txscript.ErrNotClaimScript {
|
||||||
|
@ -129,7 +126,8 @@ func (h *handler) handleTxOuts(ct *claimtrie.ClaimTrie) error {
|
||||||
copy(id[:], cs.ClaimID())
|
copy(id[:], cs.ClaimID())
|
||||||
normName := node.NormalizeIfNecessary(name, ct.Height())
|
normName := node.NormalizeIfNecessary(name, ct.Height())
|
||||||
if !bytes.Equal(h.spent[id.Key()], 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())
|
node.LogOnce(fmt.Sprintf("Invalid update operation: name or ID mismatch at %d for: %s, %s",
|
||||||
|
ct.Height(), normName, id.String()))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package blockrepo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
|
||||||
|
@ -16,31 +16,22 @@ type Pebble struct {
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
func NewPebble(path string) (*Pebble, error) {
|
||||||
|
|
||||||
db, err := pebble.Open(path, nil)
|
db, err := pebble.Open(path, nil)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := &Pebble{db: db}
|
repo := &Pebble{db: db}
|
||||||
|
|
||||||
return repo, nil
|
return repo, errors.Wrapf(err, "unable to open %s", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Load() (int32, error) {
|
func (repo *Pebble) Load() (int32, error) {
|
||||||
|
|
||||||
iter := repo.db.NewIter(nil)
|
iter := repo.db.NewIter(nil)
|
||||||
if !iter.Last() {
|
if !iter.Last() {
|
||||||
if err := iter.Close(); err != nil {
|
err := iter.Close()
|
||||||
return 0, fmt.Errorf("close iter: %w", err)
|
return 0, errors.Wrap(err, "closing iterator with no last")
|
||||||
}
|
|
||||||
return 0, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
height := int32(binary.BigEndian.Uint32(iter.Key()))
|
height := int32(binary.BigEndian.Uint32(iter.Key()))
|
||||||
if err := iter.Close(); err != nil {
|
err := iter.Close()
|
||||||
return height, fmt.Errorf("close iter: %w", err)
|
return height, errors.Wrap(err, "closing iterator")
|
||||||
}
|
|
||||||
|
|
||||||
return height, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Get(height int32) (*chainhash.Hash, error) {
|
func (repo *Pebble) Get(height int32) (*chainhash.Hash, error) {
|
||||||
|
@ -49,14 +40,14 @@ func (repo *Pebble) Get(height int32) (*chainhash.Hash, error) {
|
||||||
binary.BigEndian.PutUint32(key, uint32(height))
|
binary.BigEndian.PutUint32(key, uint32(height))
|
||||||
|
|
||||||
b, closer, err := repo.db.Get(key)
|
b, closer, err := repo.db.Get(key)
|
||||||
if err != nil {
|
if closer != nil {
|
||||||
return nil, err
|
defer closer.Close()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "in get")
|
||||||
}
|
}
|
||||||
defer closer.Close()
|
|
||||||
|
|
||||||
hash, err := chainhash.NewHash(b)
|
hash, err := chainhash.NewHash(b)
|
||||||
|
return hash, errors.Wrap(err, "creating hash")
|
||||||
return hash, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Set(height int32, hash *chainhash.Hash) error {
|
func (repo *Pebble) Set(height int32, hash *chainhash.Hash) error {
|
||||||
|
@ -64,20 +55,17 @@ func (repo *Pebble) Set(height int32, hash *chainhash.Hash) error {
|
||||||
key := make([]byte, 4)
|
key := make([]byte, 4)
|
||||||
binary.BigEndian.PutUint32(key, uint32(height))
|
binary.BigEndian.PutUint32(key, uint32(height))
|
||||||
|
|
||||||
return repo.db.Set(key, hash[:], pebble.NoSync)
|
return errors.WithStack(repo.db.Set(key, hash[:], pebble.NoSync))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Close() error {
|
func (repo *Pebble) Close() error {
|
||||||
|
|
||||||
err := repo.db.Flush()
|
err := repo.db.Flush()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble fludh: %w", err)
|
// if we fail to close are we going to try again later?
|
||||||
|
return errors.Wrap(err, "on flush")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
if err != nil {
|
return errors.Wrap(err, "on close")
|
||||||
return fmt.Errorf("pebble close: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package chainrepo
|
package chainrepo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/claimtrie/change"
|
"github.com/btcsuite/btcd/claimtrie/change"
|
||||||
"github.com/vmihailenco/msgpack/v5"
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
@ -18,13 +17,9 @@ type Pebble struct {
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
func NewPebble(path string) (*Pebble, error) {
|
||||||
|
|
||||||
db, err := pebble.Open(path, nil)
|
db, err := pebble.Open(path, nil)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := &Pebble{db: db}
|
repo := &Pebble{db: db}
|
||||||
|
|
||||||
return repo, nil
|
return repo, errors.Wrapf(err, "unable to open %s", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Save(height int32, changes []change.Change) error {
|
func (repo *Pebble) Save(height int32, changes []change.Change) error {
|
||||||
|
@ -33,59 +28,44 @@ func (repo *Pebble) Save(height int32, changes []change.Change) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
key := bytes.NewBuffer(nil)
|
var key [4]byte
|
||||||
err := binary.Write(key, binary.BigEndian, height)
|
binary.BigEndian.PutUint32(key[:], uint32(height))
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("pebble prepare key: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
value, err := msgpack.Marshal(changes)
|
value, err := msgpack.Marshal(changes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble msgpack marshal: %w", err)
|
return errors.Wrap(err, "in marshaller")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.db.Set(key.Bytes(), value, pebble.NoSync)
|
err = repo.db.Set(key[:], value, pebble.NoSync)
|
||||||
if err != nil {
|
return errors.Wrap(err, "in set")
|
||||||
return fmt.Errorf("pebble set: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Load(height int32) ([]change.Change, error) {
|
func (repo *Pebble) Load(height int32) ([]change.Change, error) {
|
||||||
|
|
||||||
key := bytes.NewBuffer(nil)
|
var key [4]byte
|
||||||
err := binary.Write(key, binary.BigEndian, height)
|
binary.BigEndian.PutUint32(key[:], uint32(height))
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("pebble prepare key: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b, closer, err := repo.db.Get(key.Bytes())
|
b, closer, err := repo.db.Get(key[:])
|
||||||
if err != nil {
|
if closer != nil {
|
||||||
return nil, err
|
defer closer.Close()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "in get")
|
||||||
}
|
}
|
||||||
defer closer.Close()
|
|
||||||
|
|
||||||
var changes []change.Change
|
var changes []change.Change
|
||||||
err = msgpack.Unmarshal(b, &changes)
|
err = msgpack.Unmarshal(b, &changes)
|
||||||
if err != nil {
|
return changes, errors.Wrap(err, "in unmarshaller")
|
||||||
return nil, fmt.Errorf("pebble msgpack marshal: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return changes, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Close() error {
|
func (repo *Pebble) Close() error {
|
||||||
|
|
||||||
err := repo.db.Flush()
|
err := repo.db.Flush()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble fludh: %w", err)
|
// if we fail to close are we going to try again later?
|
||||||
|
return errors.Wrap(err, "on flush")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
if err != nil {
|
return errors.Wrap(err, "on close")
|
||||||
return fmt.Errorf("pebble close: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package claimtrie
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
@ -64,13 +65,13 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
||||||
|
|
||||||
blockRepo, err := blockrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.BlockRepoPebble.Path))
|
blockRepo, err := blockrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.BlockRepoPebble.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new block repo: %w", err)
|
return nil, errors.Wrap(err, "creating block repo")
|
||||||
}
|
}
|
||||||
cleanups = append(cleanups, blockRepo.Close)
|
cleanups = append(cleanups, blockRepo.Close)
|
||||||
|
|
||||||
temporalRepo, err := temporalrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.TemporalRepoPebble.Path))
|
temporalRepo, err := temporalrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.TemporalRepoPebble.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new temporal repo: %w", err)
|
return nil, errors.Wrap(err, "creating temporal repo")
|
||||||
}
|
}
|
||||||
cleanups = append(cleanups, temporalRepo.Close)
|
cleanups = append(cleanups, temporalRepo.Close)
|
||||||
|
|
||||||
|
@ -78,12 +79,12 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
||||||
// The cleanup is delegated to the Node Manager.
|
// The cleanup is delegated to the Node Manager.
|
||||||
nodeRepo, err := noderepo.NewPebble(filepath.Join(cfg.DataDir, cfg.NodeRepoPebble.Path))
|
nodeRepo, err := noderepo.NewPebble(filepath.Join(cfg.DataDir, cfg.NodeRepoPebble.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new node repo: %w", err)
|
return nil, errors.Wrap(err, "creating node repo")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseManager, err := node.NewBaseManager(nodeRepo)
|
baseManager, err := node.NewBaseManager(nodeRepo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new node manager: %w", err)
|
return nil, errors.Wrap(err, "creating node base manager")
|
||||||
}
|
}
|
||||||
nodeManager := node.NewNormalizingManager(baseManager)
|
nodeManager := node.NewNormalizingManager(baseManager)
|
||||||
cleanups = append(cleanups, nodeManager.Close)
|
cleanups = append(cleanups, nodeManager.Close)
|
||||||
|
@ -96,7 +97,7 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
||||||
// Initialize repository for MerkleTrie. The cleanup is delegated to MerkleTrie.
|
// Initialize repository for MerkleTrie. The cleanup is delegated to MerkleTrie.
|
||||||
trieRepo, err := merkletrierepo.NewPebble(filepath.Join(cfg.DataDir, cfg.MerkleTrieRepoPebble.Path))
|
trieRepo, err := merkletrierepo.NewPebble(filepath.Join(cfg.DataDir, cfg.MerkleTrieRepoPebble.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new trie repo: %w", err)
|
return nil, errors.Wrap(err, "creating trie repo")
|
||||||
}
|
}
|
||||||
|
|
||||||
persistentTrie := merkletrie.NewPersistentTrie(nodeManager, trieRepo)
|
persistentTrie := merkletrie.NewPersistentTrie(nodeManager, trieRepo)
|
||||||
|
@ -107,7 +108,7 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
||||||
// Restore the last height.
|
// Restore the last height.
|
||||||
previousHeight, err := blockRepo.Load()
|
previousHeight, err := blockRepo.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("load blocks: %w", err)
|
return nil, errors.Wrap(err, "load block tip")
|
||||||
}
|
}
|
||||||
|
|
||||||
ct := &ClaimTrie{
|
ct := &ClaimTrie{
|
||||||
|
@ -123,14 +124,14 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
||||||
if cfg.Record {
|
if cfg.Record {
|
||||||
chainRepo, err := chainrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.ChainRepoPebble.Path))
|
chainRepo, err := chainrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.ChainRepoPebble.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new change change repo: %w", err)
|
return nil, errors.Wrap(err, "creating chain repo")
|
||||||
}
|
}
|
||||||
cleanups = append(cleanups, chainRepo.Close)
|
cleanups = append(cleanups, chainRepo.Close)
|
||||||
ct.chainRepo = chainRepo
|
ct.chainRepo = chainRepo
|
||||||
|
|
||||||
reportedBlockRepo, err := blockrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.ReportedBlockRepoPebble.Path))
|
reportedBlockRepo, err := blockrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.ReportedBlockRepoPebble.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new reported block repo: %w", err)
|
return nil, errors.Wrap(err, "creating reported block repo")
|
||||||
}
|
}
|
||||||
cleanups = append(cleanups, reportedBlockRepo.Close)
|
cleanups = append(cleanups, reportedBlockRepo.Close)
|
||||||
ct.reportedBlockRepo = reportedBlockRepo
|
ct.reportedBlockRepo = reportedBlockRepo
|
||||||
|
@ -141,19 +142,19 @@ func New(cfg config.Config) (*ClaimTrie, error) {
|
||||||
hash, err := blockRepo.Get(previousHeight)
|
hash, err := blockRepo.Get(previousHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Close() // TODO: the cleanups aren't run when we exit with an err above here (but should be)
|
ct.Close() // TODO: the cleanups aren't run when we exit with an err above here (but should be)
|
||||||
return nil, fmt.Errorf("get hash: %w", err)
|
return nil, errors.Wrap(err, "block repo get")
|
||||||
}
|
}
|
||||||
_, err = nodeManager.IncrementHeightTo(previousHeight)
|
_, err = nodeManager.IncrementHeightTo(previousHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Close()
|
ct.Close()
|
||||||
return nil, fmt.Errorf("node manager init: %w", err)
|
return nil, errors.Wrap(err, "increment height to")
|
||||||
}
|
}
|
||||||
// TODO: pass in the interrupt signal here:
|
// TODO: pass in the interrupt signal here:
|
||||||
trie.SetRoot(hash, nil) // keep this after IncrementHeightTo
|
trie.SetRoot(hash, nil) // keep this after IncrementHeightTo
|
||||||
|
|
||||||
if !ct.MerkleHash().IsEqual(hash) {
|
if !ct.MerkleHash().IsEqual(hash) {
|
||||||
ct.Close()
|
ct.Close()
|
||||||
return nil, fmt.Errorf("unable to restore the claim hash to %s at height %d", hash.String(), previousHeight)
|
return nil, errors.Errorf("unable to restore the claim hash to %s at height %d", hash.String(), previousHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,19 +237,19 @@ func (ct *ClaimTrie) AppendBlock() error {
|
||||||
if len(ct.changes) > 0 && ct.chainRepo != nil {
|
if len(ct.changes) > 0 && ct.chainRepo != nil {
|
||||||
err := ct.chainRepo.Save(ct.height, ct.changes)
|
err := ct.chainRepo.Save(ct.height, ct.changes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("chain change repo save: %w", err)
|
return errors.Wrap(err, "chain change repo save")
|
||||||
}
|
}
|
||||||
ct.changes = ct.changes[:0]
|
ct.changes = ct.changes[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
names, err := ct.nodeManager.IncrementHeightTo(ct.height)
|
names, err := ct.nodeManager.IncrementHeightTo(ct.height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("node mgr increment: %w", err)
|
return errors.Wrap(err, "node manager increment")
|
||||||
}
|
}
|
||||||
|
|
||||||
expirations, err := ct.temporalRepo.NodesAt(ct.height)
|
expirations, err := ct.temporalRepo.NodesAt(ct.height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("temporal repo nodes at: %w", err)
|
return errors.Wrap(err, "temporal repo get")
|
||||||
}
|
}
|
||||||
|
|
||||||
names = removeDuplicates(names) // comes out sorted
|
names = removeDuplicates(names) // comes out sorted
|
||||||
|
@ -275,7 +276,7 @@ func (ct *ClaimTrie) AppendBlock() error {
|
||||||
}
|
}
|
||||||
err = ct.temporalRepo.SetNodesAt(updateNames, updateHeights)
|
err = ct.temporalRepo.SetNodesAt(updateNames, updateHeights)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("temporal repo set at: %w", err)
|
return errors.Wrap(err, "temporal repo set")
|
||||||
}
|
}
|
||||||
|
|
||||||
hitFork := ct.updateTrieForHashForkIfNecessary()
|
hitFork := ct.updateTrieForHashForkIfNecessary()
|
||||||
|
@ -294,14 +295,16 @@ func (ct *ClaimTrie) updateTrieForHashForkIfNecessary() bool {
|
||||||
if ct.height != param.AllClaimsInMerkleForkHeight {
|
if ct.height != param.AllClaimsInMerkleForkHeight {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fmt.Printf("Marking all trie nodes as dirty for the hash fork...")
|
|
||||||
|
node.LogOnce("Marking all trie nodes as dirty for the hash fork...")
|
||||||
|
|
||||||
// invalidate all names because we have to recompute the hash on everything
|
// invalidate all names because we have to recompute the hash on everything
|
||||||
// requires its own 8GB of RAM in current trie impl.
|
|
||||||
ct.nodeManager.IterateNames(func(name []byte) bool {
|
ct.nodeManager.IterateNames(func(name []byte) bool {
|
||||||
ct.merkleTrie.Update(name, false)
|
ct.merkleTrie.Update(name, false)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
fmt.Printf(" Done. Now recomputing all hashes...\n")
|
|
||||||
|
node.LogOnce("Done. Now recomputing all hashes...")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +361,7 @@ func (ct *ClaimTrie) ResetHeight(height int32) error {
|
||||||
ct.merkleTrie.SetRoot(hash, names)
|
ct.merkleTrie.SetRoot(hash, names)
|
||||||
|
|
||||||
if !ct.MerkleHash().IsEqual(hash) {
|
if !ct.MerkleHash().IsEqual(hash) {
|
||||||
return fmt.Errorf("unable to restore the hash at height %d", height)
|
return errors.Errorf("unable to restore the hash at height %d", height)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -378,17 +381,15 @@ func (ct *ClaimTrie) Height() int32 {
|
||||||
|
|
||||||
// Close persists states.
|
// Close persists states.
|
||||||
// Any calls to the ClaimTrie after Close() being called results undefined behaviour.
|
// Any calls to the ClaimTrie after Close() being called results undefined behaviour.
|
||||||
func (ct *ClaimTrie) Close() error {
|
func (ct *ClaimTrie) Close() {
|
||||||
|
|
||||||
for i := len(ct.cleanups) - 1; i >= 0; i-- {
|
for i := len(ct.cleanups) - 1; i >= 0; i-- {
|
||||||
cleanup := ct.cleanups[i]
|
cleanup := ct.cleanups[i]
|
||||||
err := cleanup()
|
err := cleanup()
|
||||||
if err != nil { // TODO: it would be better to cleanup what we can than exit
|
if err != nil { // it would be better to cleanup what we can than exit early
|
||||||
return fmt.Errorf("cleanup: %w", err)
|
node.LogOnce("On cleanup: " + err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *ClaimTrie) forwardNodeChange(chg change.Change) error {
|
func (ct *ClaimTrie) forwardNodeChange(chg change.Change) error {
|
||||||
|
|
|
@ -40,10 +40,7 @@ func TestFixedHashes(t *testing.T) {
|
||||||
setup(t)
|
setup(t)
|
||||||
ct, err := New(cfg)
|
ct, err := New(cfg)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
defer func() {
|
defer ct.Close()
|
||||||
err = ct.Close()
|
|
||||||
r.NoError(err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
r.Equal(merkletrie.EmptyTrieHash[:], ct.MerkleHash()[:])
|
r.Equal(merkletrie.EmptyTrieHash[:], ct.MerkleHash()[:])
|
||||||
|
|
||||||
|
@ -81,10 +78,7 @@ func TestNormalizationFork(t *testing.T) {
|
||||||
ct, err := New(cfg)
|
ct, err := New(cfg)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
r.NotNil(ct)
|
r.NotNil(ct)
|
||||||
defer func() {
|
defer ct.Close()
|
||||||
err = ct.Close()
|
|
||||||
r.NoError(err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
hash := chainhash.HashH([]byte{1, 2, 3})
|
hash := chainhash.HashH([]byte{1, 2, 3})
|
||||||
|
|
||||||
|
@ -145,10 +139,7 @@ func TestActivationsOnNormalizationFork(t *testing.T) {
|
||||||
ct, err := New(cfg)
|
ct, err := New(cfg)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
r.NotNil(ct)
|
r.NotNil(ct)
|
||||||
defer func() {
|
defer ct.Close()
|
||||||
err = ct.Close()
|
|
||||||
r.NoError(err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
hash := chainhash.HashH([]byte{1, 2, 3})
|
hash := chainhash.HashH([]byte{1, 2, 3})
|
||||||
|
|
||||||
|
@ -191,10 +182,7 @@ func TestNormalizationSortOrder(t *testing.T) {
|
||||||
ct, err := New(cfg)
|
ct, err := New(cfg)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
r.NotNil(ct)
|
r.NotNil(ct)
|
||||||
defer func() {
|
defer ct.Close()
|
||||||
err := ct.Close()
|
|
||||||
r.NoError(err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
hash := chainhash.HashH([]byte{1, 2, 3})
|
hash := chainhash.HashH([]byte{1, 2, 3})
|
||||||
|
|
||||||
|
@ -238,10 +226,7 @@ func TestRebuild(t *testing.T) {
|
||||||
ct, err := New(cfg)
|
ct, err := New(cfg)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
r.NotNil(ct)
|
r.NotNil(ct)
|
||||||
defer func() {
|
defer ct.Close()
|
||||||
err := ct.Close()
|
|
||||||
r.NoError(err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
hash := chainhash.HashH([]byte{1, 2, 3})
|
hash := chainhash.HashH([]byte{1, 2, 3})
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"github.com/btcsuite/btcd/claimtrie/block/blockrepo"
|
"github.com/btcsuite/btcd/claimtrie/block/blockrepo"
|
||||||
"github.com/btcsuite/btcd/claimtrie/merkletrie"
|
"github.com/btcsuite/btcd/claimtrie/merkletrie"
|
||||||
"github.com/btcsuite/btcd/claimtrie/merkletrie/merkletrierepo"
|
"github.com/btcsuite/btcd/claimtrie/merkletrie/merkletrierepo"
|
||||||
"github.com/btcsuite/btcd/claimtrie/param"
|
|
||||||
"github.com/btcsuite/btcd/claimtrie/temporal/temporalrepo"
|
"github.com/btcsuite/btcd/claimtrie/temporal/temporalrepo"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -139,7 +138,7 @@ var blockNameCmd = &cobra.Command{
|
||||||
defer trie.Close()
|
defer trie.Close()
|
||||||
trie.SetRoot(hash, nil)
|
trie.SetRoot(hash, nil)
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
trie.Dump(args[1], param.AllClaimsInMerkleForkHeight >= int32(height))
|
trie.Dump(args[1])
|
||||||
} else {
|
} else {
|
||||||
tmpRepo, err := temporalrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.TemporalRepoPebble.Path))
|
tmpRepo, err := temporalrepo.NewPebble(filepath.Join(cfg.DataDir, cfg.TemporalRepoPebble.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -151,7 +150,7 @@ var blockNameCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
for _, name := range nodes {
|
for _, name := range nodes {
|
||||||
fmt.Printf("Name: %s, ", string(name))
|
fmt.Printf("Name: %s, ", string(name))
|
||||||
trie.Dump(string(name), param.AllClaimsInMerkleForkHeight >= int32(height))
|
trie.Dump(string(name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -84,11 +84,11 @@ var nodeReplayCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nm, err := node.NewBaseManager(repo)
|
bm, err := node.NewBaseManager(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("create node manager: %w", err)
|
return fmt.Errorf("create node manager: %w", err)
|
||||||
}
|
}
|
||||||
nm = node.NewNormalizingManager(nm)
|
nm := node.NewNormalizingManager(bm)
|
||||||
|
|
||||||
_, err = nm.IncrementHeightTo(int32(height))
|
_, err = nm.IncrementHeightTo(int32(height))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -3,14 +3,13 @@ package merkletrie
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
|
|
||||||
"github.com/cockroachdb/pebble"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -97,7 +96,7 @@ func (t *PersistentTrie) resolveChildLinks(n *vertex, key []byte) {
|
||||||
b.Write(n.merkleHash[:])
|
b.Write(n.merkleHash[:])
|
||||||
|
|
||||||
result, closer, err := t.repo.Get(b.Bytes())
|
result, closer, err := t.repo.Get(b.Bytes())
|
||||||
if err == pebble.ErrNotFound { // TODO: leaky abstraction
|
if result == nil {
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -247,10 +246,13 @@ func (t *PersistentTrie) merkleAllClaims(prefix []byte, v *vertex) *chainhash.Ha
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *PersistentTrie) Close() error {
|
func (t *PersistentTrie) Close() error {
|
||||||
return t.repo.Close()
|
return errors.WithStack(t.repo.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *PersistentTrie) Dump(s string, allClaims bool) {
|
func (t *PersistentTrie) Dump(s string) {
|
||||||
|
// TODO: this function is in the wrong spot; either it goes with its caller or it needs to be a generic iterator
|
||||||
|
// we don't want fmt used in here either way
|
||||||
|
|
||||||
v := t.root
|
v := t.root
|
||||||
|
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
package merkletrierepo
|
package merkletrierepo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cockroachdb/pebble"
|
"github.com/cockroachdb/pebble"
|
||||||
humanize "github.com/dustin/go-humanize"
|
"github.com/pkg/errors"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pebble struct {
|
type Pebble struct {
|
||||||
|
@ -16,37 +13,35 @@ type Pebble struct {
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
func NewPebble(path string) (*Pebble, error) {
|
||||||
|
|
||||||
cache := pebble.NewCache(512 << 20)
|
cache := pebble.NewCache(512 << 20)
|
||||||
defer cache.Unref()
|
//defer cache.Unref()
|
||||||
|
//
|
||||||
go func() {
|
//go func() {
|
||||||
tick := time.NewTicker(60 * time.Second)
|
// tick := time.NewTicker(60 * time.Second)
|
||||||
for range tick.C {
|
// for range tick.C {
|
||||||
|
//
|
||||||
m := cache.Metrics()
|
// m := cache.Metrics()
|
||||||
fmt.Printf("cnt: %s, objs: %s, hits: %s, miss: %s, hitrate: %.2f\n",
|
// fmt.Printf("cnt: %s, objs: %s, hits: %s, miss: %s, hitrate: %.2f\n",
|
||||||
humanize.Bytes(uint64(m.Size)),
|
// humanize.Bytes(uint64(m.Size)),
|
||||||
humanize.Comma(m.Count),
|
// humanize.Comma(m.Count),
|
||||||
humanize.Comma(m.Hits),
|
// humanize.Comma(m.Hits),
|
||||||
humanize.Comma(m.Misses),
|
// humanize.Comma(m.Misses),
|
||||||
float64(m.Hits)/float64(m.Hits+m.Misses))
|
// float64(m.Hits)/float64(m.Hits+m.Misses))
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}()
|
//}()
|
||||||
|
|
||||||
db, err := pebble.Open(path, &pebble.Options{Cache: cache, BytesPerSync: 32 << 20})
|
db, err := pebble.Open(path, &pebble.Options{Cache: cache, BytesPerSync: 32 << 20})
|
||||||
if err != nil {
|
repo := &Pebble{db: db}
|
||||||
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := &Pebble{
|
return repo, errors.Wrapf(err, "unable to open %s", path)
|
||||||
db: db,
|
|
||||||
}
|
|
||||||
|
|
||||||
return repo, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Get(key []byte) ([]byte, io.Closer, error) {
|
func (repo *Pebble) Get(key []byte) ([]byte, io.Closer, error) {
|
||||||
return repo.db.Get(key)
|
d, c, e := repo.db.Get(key)
|
||||||
|
if e == pebble.ErrNotFound {
|
||||||
|
return nil, c, nil
|
||||||
|
}
|
||||||
|
return d, c, e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Set(key, value []byte) error {
|
func (repo *Pebble) Set(key, value []byte) error {
|
||||||
|
@ -57,13 +52,10 @@ func (repo *Pebble) Close() error {
|
||||||
|
|
||||||
err := repo.db.Flush()
|
err := repo.db.Flush()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble fludh: %w", err)
|
// if we fail to close are we going to try again later?
|
||||||
|
return errors.Wrap(err, "on flush")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
if err != nil {
|
return errors.Wrap(err, "on close")
|
||||||
return fmt.Errorf("pebble close: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package merkletrie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -42,8 +41,15 @@ func (rt *RamTrie) SetRoot(h *chainhash.Hash, names [][]byte) {
|
||||||
|
|
||||||
// if names is nil then we need to query all names
|
// if names is nil then we need to query all names
|
||||||
if names == nil {
|
if names == nil {
|
||||||
fmt.Printf("Building the entire claim trie in RAM...\n")
|
node.LogOnce("Building the entire claim trie in RAM...") // could put this in claimtrie.go
|
||||||
// TODO: should technically clear the old trie first
|
|
||||||
|
//should technically clear the old trie first:
|
||||||
|
if rt.Nodes > 1 {
|
||||||
|
rt.Root = &collapsedVertex{key: make(KeyType, 0)}
|
||||||
|
rt.Nodes = 1
|
||||||
|
runtime.GC()
|
||||||
|
}
|
||||||
|
|
||||||
rt.store.IterateNames(func(name []byte) bool {
|
rt.store.IterateNames(func(name []byte) bool {
|
||||||
rt.Update(name, false)
|
rt.Update(name, false)
|
||||||
return true
|
return true
|
||||||
|
@ -134,6 +140,7 @@ func (rt *RamTrie) merkleHashAllClaims(v *collapsedVertex) *chainhash.Hash {
|
||||||
|
|
||||||
childHash := NoChildrenHash
|
childHash := NoChildrenHash
|
||||||
if len(childHashes) > 0 {
|
if len(childHashes) > 0 {
|
||||||
|
// this shouldn't be referencing node; where else can we put this merkle root func?
|
||||||
childHash = node.ComputeMerkleRoot(childHashes)
|
childHash = node.ComputeMerkleRoot(childHashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package claimtrie
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btclog"
|
"github.com/btcsuite/btclog"
|
||||||
|
@ -26,3 +26,12 @@ func DisableLog() {
|
||||||
func UseLogger(logger btclog.Logger) {
|
func UseLogger(logger btclog.Logger) {
|
||||||
log = logger
|
log = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var loggedStrings = map[string]bool{} // is this gonna get too large?
|
||||||
|
func LogOnce(s string) {
|
||||||
|
if loggedStrings[s] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loggedStrings[s] = true
|
||||||
|
log.Info(s)
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
@ -85,7 +86,7 @@ type BaseManager struct {
|
||||||
changes []change.Change
|
changes []change.Change
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBaseManager(repo Repo) (Manager, error) {
|
func NewBaseManager(repo Repo) (*BaseManager, error) {
|
||||||
|
|
||||||
nm := &BaseManager{
|
nm := &BaseManager{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
|
@ -107,12 +108,12 @@ func (nm *BaseManager) Node(name []byte) (*Node, error) {
|
||||||
|
|
||||||
changes, err := nm.repo.LoadChanges(name)
|
changes, err := nm.repo.LoadChanges(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("load changes from node repo: %w", err)
|
return nil, errors.Wrap(err, "in load changes")
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err = nm.newNodeFromChanges(changes, nm.height)
|
n, err = nm.newNodeFromChanges(changes, nm.height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("create node from changes: %w", err)
|
return nil, errors.Wrap(err, "in new node")
|
||||||
}
|
}
|
||||||
|
|
||||||
if n == nil { // they've requested a nonexistent or expired name
|
if n == nil { // they've requested a nonexistent or expired name
|
||||||
|
@ -137,7 +138,7 @@ func (nm *BaseManager) newNodeFromChanges(changes []change.Change, height int32)
|
||||||
|
|
||||||
for i, chg := range changes {
|
for i, chg := range changes {
|
||||||
if chg.Height < previous {
|
if chg.Height < previous {
|
||||||
return nil, fmt.Errorf("expected the changes to be in order by height")
|
panic("expected the changes to be in order by height")
|
||||||
}
|
}
|
||||||
if chg.Height > height {
|
if chg.Height > height {
|
||||||
count = i
|
count = i
|
||||||
|
@ -152,7 +153,7 @@ func (nm *BaseManager) newNodeFromChanges(changes []change.Change, height int32)
|
||||||
delay := nm.getDelayForName(n, chg)
|
delay := nm.getDelayForName(n, chg)
|
||||||
err := n.ApplyChange(chg, delay)
|
err := n.ApplyChange(chg, delay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("append change: %w", err)
|
return nil, errors.Wrap(err, "in apply change")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +169,9 @@ func (nm *BaseManager) AppendChange(chg change.Change) error {
|
||||||
nm.cache.Delete(string(chg.Name))
|
nm.cache.Delete(string(chg.Name))
|
||||||
nm.changes = append(nm.changes, chg)
|
nm.changes = append(nm.changes, chg)
|
||||||
|
|
||||||
|
// worth putting in this kind of thing pre-emptively?
|
||||||
|
// log.Debugf("CHG: %d, %s, %v, %s, %d", chg.Height, chg.Name, chg.Type, chg.ClaimID, chg.Amount)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +229,7 @@ func (nm *BaseManager) IncrementHeightTo(height int32) ([][]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := nm.repo.AppendChanges(nm.changes); err != nil { // destroys names
|
if err := nm.repo.AppendChanges(nm.changes); err != nil { // destroys names
|
||||||
return nil, fmt.Errorf("save changes to node repo: %w", err)
|
return nil, errors.Wrap(err, "in append changes")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate the buffer size to zero.
|
// Truncate the buffer size to zero.
|
||||||
|
@ -241,13 +245,13 @@ func (nm *BaseManager) IncrementHeightTo(height int32) ([][]byte, error) {
|
||||||
|
|
||||||
func (nm *BaseManager) DecrementHeightTo(affectedNames [][]byte, height int32) error {
|
func (nm *BaseManager) DecrementHeightTo(affectedNames [][]byte, height int32) error {
|
||||||
if height >= nm.height {
|
if height >= nm.height {
|
||||||
return fmt.Errorf("invalid height")
|
return errors.Errorf("invalid height of %d for %d", height, nm.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range affectedNames {
|
for _, name := range affectedNames {
|
||||||
nm.cache.Delete(string(name))
|
nm.cache.Delete(string(name))
|
||||||
if err := nm.repo.DropChanges(name, height); err != nil {
|
if err := nm.repo.DropChanges(name, height); err != nil {
|
||||||
return err
|
return errors.Wrap(err, "in drop changes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,25 +279,15 @@ func (nm *BaseManager) getDelayForName(n *Node, chg change.Change) int32 {
|
||||||
|
|
||||||
delay := calculateDelay(chg.Height, n.TakenOverAt)
|
delay := calculateDelay(chg.Height, n.TakenOverAt)
|
||||||
if delay > 0 && nm.aWorkaroundIsNeeded(n, chg) {
|
if delay > 0 && nm.aWorkaroundIsNeeded(n, chg) {
|
||||||
// TODO: log this (but only once per name-height combo)
|
if chg.Height >= nm.height {
|
||||||
//fmt.Printf("Delay workaround applies to %s at %d\n", chg.Name, chg.Height)
|
LogOnce(fmt.Sprintf("Delay workaround applies to %s at %d, ClaimID: %s",
|
||||||
|
chg.Name, chg.Height, chg.ClaimID))
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return delay
|
return delay
|
||||||
}
|
}
|
||||||
|
|
||||||
func isInDelayPart2(chg change.Change) bool {
|
|
||||||
heights, ok := param.DelayWorkaroundsPart2[string(chg.Name)]
|
|
||||||
if ok {
|
|
||||||
for _, h := range heights {
|
|
||||||
if h == chg.Height {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasZeroActiveClaims(n *Node) bool {
|
func hasZeroActiveClaims(n *Node) bool {
|
||||||
// this isn't quite the same as having an active best (since that is only updated after all changes are processed)
|
// this isn't quite the same as having an active best (since that is only updated after all changes are processed)
|
||||||
for _, c := range n.Claims {
|
for _, c := range n.Claims {
|
||||||
|
@ -318,19 +312,7 @@ func (nm *BaseManager) aWorkaroundIsNeeded(n *Node, chg change.Change) bool {
|
||||||
// auto it = nodesToAddOrUpdate.find(name); // nodesToAddOrUpdate is the working changes, base is previous block
|
// auto it = nodesToAddOrUpdate.find(name); // nodesToAddOrUpdate is the working changes, base is previous block
|
||||||
// auto answer = (it || (it = base->find(name))) && !it->empty() ? nNextHeight - it->nHeightOfLastTakeover : 0;
|
// auto answer = (it || (it = base->find(name))) && !it->empty() ? nNextHeight - it->nHeightOfLastTakeover : 0;
|
||||||
|
|
||||||
needed := hasZeroActiveClaims(n) && nm.hasChildren(chg.Name, chg.Height, chg.SpentChildren, 2)
|
return hasZeroActiveClaims(n) && nm.hasChildren(chg.Name, chg.Height, chg.SpentChildren, 2)
|
||||||
if chg.Height <= 933294 {
|
|
||||||
w := isInDelayPart2(chg)
|
|
||||||
if w {
|
|
||||||
if !needed {
|
|
||||||
fmt.Printf("DELAY WORKAROUND FALSE NEGATIVE! %d: %s: %t\n", chg.Height, chg.Name, needed)
|
|
||||||
}
|
|
||||||
} else if needed {
|
|
||||||
fmt.Printf("DELAY WORKAROUND FALSE POSITIVE! %d: %s: %t\n", chg.Height, chg.Name, needed)
|
|
||||||
}
|
|
||||||
// return w // if you want to sync to 933294+
|
|
||||||
}
|
|
||||||
return needed
|
|
||||||
} else if len(n.Claims) > 0 {
|
} else if len(n.Claims) > 0 {
|
||||||
// NOTE: old code had a bug in it where nodes with no claims but with children would get left in the cache after removal.
|
// NOTE: old code had a bug in it where nodes with no claims but with children would get left in the cache after removal.
|
||||||
// This would cause the getNumBlocksOfContinuousOwnership to return zero (causing incorrect takeover height calc).
|
// This would cause the getNumBlocksOfContinuousOwnership to return zero (causing incorrect takeover height calc).
|
||||||
|
@ -371,13 +353,7 @@ func (nm *BaseManager) Height() int32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nm *BaseManager) Close() error {
|
func (nm *BaseManager) Close() error {
|
||||||
|
return errors.WithStack(nm.repo.Close())
|
||||||
err := nm.repo.Close()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("close repo: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nm *BaseManager) hasChildren(name []byte, height int32, spentChildren map[string]bool, required int) bool {
|
func (nm *BaseManager) hasChildren(name []byte, height int32, spentChildren map[string]bool, required int) bool {
|
||||||
|
@ -386,7 +362,7 @@ func (nm *BaseManager) hasChildren(name []byte, height int32, spentChildren map[
|
||||||
spentChildren = map[string]bool{}
|
spentChildren = map[string]bool{}
|
||||||
}
|
}
|
||||||
|
|
||||||
nm.repo.IterateChildren(name, func(changes []change.Change) bool {
|
err := nm.repo.IterateChildren(name, func(changes []change.Change) bool {
|
||||||
// if the key is unseen, generate a node for it to height
|
// if the key is unseen, generate a node for it to height
|
||||||
// if that node is active then increase the count
|
// if that node is active then increase the count
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
|
@ -407,7 +383,7 @@ func (nm *BaseManager) hasChildren(name []byte, height int32, spentChildren map[
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return len(c) >= required
|
return err == nil && len(c) >= required
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nm *BaseManager) IterateNames(predicate func(name []byte) bool) {
|
func (nm *BaseManager) IterateNames(predicate func(name []byte) bool) {
|
||||||
|
|
|
@ -185,3 +185,44 @@ func TestClaimSort(t *testing.T) {
|
||||||
r.Equal(int64(2), n.Claims[2].Amount)
|
r.Equal(int64(2), n.Claims[2].Amount)
|
||||||
r.Equal(int32(4), n.Claims[3].AcceptedAt)
|
r.Equal(int32(4), n.Claims[3].AcceptedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHasChildren(t *testing.T) {
|
||||||
|
r := require.New(t)
|
||||||
|
|
||||||
|
param.SetNetwork(wire.TestNet)
|
||||||
|
repo, err := noderepo.NewPebble(t.TempDir())
|
||||||
|
r.NoError(err)
|
||||||
|
|
||||||
|
m, err := NewBaseManager(repo)
|
||||||
|
r.NoError(err)
|
||||||
|
defer m.Close()
|
||||||
|
|
||||||
|
chg := change.NewChange(change.AddClaim).SetName([]byte("a")).SetOutPoint(out1).SetHeight(1).SetAmount(2)
|
||||||
|
chg.ClaimID = change.NewClaimID(*out1)
|
||||||
|
r.NoError(m.AppendChange(chg))
|
||||||
|
_, err = m.IncrementHeightTo(1)
|
||||||
|
r.NoError(err)
|
||||||
|
r.False(m.hasChildren([]byte("a"), 1, nil, 1))
|
||||||
|
|
||||||
|
chg = change.NewChange(change.AddClaim).SetName([]byte("ab")).SetOutPoint(out2).SetHeight(2).SetAmount(2)
|
||||||
|
chg.ClaimID = change.NewClaimID(*out2)
|
||||||
|
r.NoError(m.AppendChange(chg))
|
||||||
|
_, err = m.IncrementHeightTo(2)
|
||||||
|
r.NoError(err)
|
||||||
|
r.False(m.hasChildren([]byte("a"), 2, nil, 2))
|
||||||
|
r.True(m.hasChildren([]byte("a"), 2, nil, 1))
|
||||||
|
|
||||||
|
chg = change.NewChange(change.AddClaim).SetName([]byte("abc")).SetOutPoint(out3).SetHeight(3).SetAmount(2)
|
||||||
|
chg.ClaimID = change.NewClaimID(*out3)
|
||||||
|
r.NoError(m.AppendChange(chg))
|
||||||
|
_, err = m.IncrementHeightTo(3)
|
||||||
|
r.NoError(err)
|
||||||
|
r.False(m.hasChildren([]byte("a"), 3, nil, 2))
|
||||||
|
|
||||||
|
chg = change.NewChange(change.AddClaim).SetName([]byte("ac")).SetOutPoint(out1).SetHeight(4).SetAmount(2)
|
||||||
|
chg.ClaimID = change.NewClaimID(*out4)
|
||||||
|
r.NoError(m.AppendChange(chg))
|
||||||
|
_, err = m.IncrementHeightTo(4)
|
||||||
|
r.NoError(err)
|
||||||
|
r.True(m.hasChildren([]byte("a"), 4, nil, 2))
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
@ -9,9 +10,6 @@ import (
|
||||||
"github.com/btcsuite/btcd/claimtrie/param"
|
"github.com/btcsuite/btcd/claimtrie/param"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNotFound is returned when a claim or support is not found.
|
|
||||||
var mispents = map[string]bool{}
|
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
BestClaim *Claim // The claim that has most effective amount at the current height.
|
BestClaim *Claim // The claim that has most effective amount at the current height.
|
||||||
TakenOverAt int32 // The height at when the current BestClaim took over.
|
TakenOverAt int32 // The height at when the current BestClaim took over.
|
||||||
|
@ -48,7 +46,7 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error {
|
||||||
}
|
}
|
||||||
old := n.Claims.find(byOut(chg.OutPoint)) // TODO: remove this after proving ResetHeight works
|
old := n.Claims.find(byOut(chg.OutPoint)) // TODO: remove this after proving ResetHeight works
|
||||||
if old != nil {
|
if old != nil {
|
||||||
fmt.Printf("CONFLICT WITH EXISTING TXO! Name: %s, Height: %d\n", chg.Name, chg.Height)
|
return errors.Errorf("CONFLICT WITH EXISTING TXO! Name: %s, Height: %d", chg.Name, chg.Height)
|
||||||
}
|
}
|
||||||
n.Claims = append(n.Claims, c)
|
n.Claims = append(n.Claims, c)
|
||||||
|
|
||||||
|
@ -56,10 +54,9 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error {
|
||||||
c := n.Claims.find(byOut(chg.OutPoint))
|
c := n.Claims.find(byOut(chg.OutPoint))
|
||||||
if c != nil {
|
if c != nil {
|
||||||
c.setStatus(Deactivated)
|
c.setStatus(Deactivated)
|
||||||
} else if !mispents[fmt.Sprintf("%d_%s", chg.Height, chg.ClaimID)] {
|
} else {
|
||||||
mispents[fmt.Sprintf("%d_%s", chg.Height, chg.ClaimID)] = true
|
LogOnce(fmt.Sprintf("Spending claim but missing existing claim with TXO %s, "+
|
||||||
fmt.Printf("Spending claim but missing existing claim with TXO %s\n "+
|
"Name: %s, ID: %s", chg.OutPoint, chg.Name, chg.ClaimID))
|
||||||
"Name: %s, ID: %s\n", chg.OutPoint, chg.Name, chg.ClaimID)
|
|
||||||
}
|
}
|
||||||
// apparently it's legit to be absent in the map:
|
// apparently it's legit to be absent in the map:
|
||||||
// 'two' at 481100, 36a719a156a1df178531f3c712b8b37f8e7cc3b36eea532df961229d936272a1:0
|
// 'two' at 481100, 36a719a156a1df178531f3c712b8b37f8e7cc3b36eea532df961229d936272a1:0
|
||||||
|
@ -81,7 +78,7 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error {
|
||||||
c.setActiveAt(chg.Height + delay) // TODO: Fork this out
|
c.setActiveAt(chg.Height + delay) // TODO: Fork this out
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Updating claim but missing existing claim with ID %s", chg.ClaimID)
|
LogOnce(fmt.Sprintf("Updating claim but missing existing claim with ID %s", chg.ClaimID))
|
||||||
}
|
}
|
||||||
case change.AddSupport:
|
case change.AddSupport:
|
||||||
n.Supports = append(n.Supports, &Claim{
|
n.Supports = append(n.Supports, &Claim{
|
||||||
|
@ -104,8 +101,8 @@ func (n *Node) ApplyChange(chg change.Change, delay int32) error {
|
||||||
// We would also need to track the update situation, though, but that could be done locally.
|
// We would also need to track the update situation, though, but that could be done locally.
|
||||||
s.setStatus(Deactivated)
|
s.setStatus(Deactivated)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Spending support but missing existing support with TXO %s\n "+
|
LogOnce(fmt.Sprintf("Spending support but missing existing claim with TXO %s, "+
|
||||||
"Name: %s, ID: %s\n", chg.OutPoint, chg.Name, chg.ClaimID)
|
"Name: %s, ID: %s", chg.OutPoint, chg.Name, chg.ClaimID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -2,7 +2,6 @@ package noderepo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
@ -12,6 +11,7 @@ import (
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
|
||||||
"github.com/cockroachdb/pebble"
|
"github.com/cockroachdb/pebble"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/vmihailenco/msgpack/v5"
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -80,19 +80,16 @@ func init() {
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
func NewPebble(path string) (*Pebble, error) {
|
||||||
|
|
||||||
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(256 << 20), BytesPerSync: 16 << 20})
|
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(256 << 20), BytesPerSync: 16 << 20})
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := &Pebble{db: db}
|
repo := &Pebble{db: db}
|
||||||
|
|
||||||
return repo, nil
|
return repo, errors.Wrapf(err, "unable to open %s", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendChanges makes an assumption that anything you pass to it is newer than what was saved before.
|
// AppendChanges makes an assumption that anything you pass to it is newer than what was saved before.
|
||||||
func (repo *Pebble) AppendChanges(changes []change.Change) error {
|
func (repo *Pebble) AppendChanges(changes []change.Change) error {
|
||||||
|
|
||||||
batch := repo.db.NewBatch()
|
batch := repo.db.NewBatch()
|
||||||
|
defer batch.Close()
|
||||||
|
|
||||||
// TODO: switch to buffer pool and reuse encoder
|
// TODO: switch to buffer pool and reuse encoder
|
||||||
for _, chg := range changes {
|
for _, chg := range changes {
|
||||||
|
@ -100,27 +97,22 @@ func (repo *Pebble) AppendChanges(changes []change.Change) error {
|
||||||
chg.Name = nil // don't waste the storage space on this (annotation a better approach?)
|
chg.Name = nil // don't waste the storage space on this (annotation a better approach?)
|
||||||
value, err := msgpack.Marshal(chg)
|
value, err := msgpack.Marshal(chg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("msgpack marshal value: %w", err)
|
return errors.Wrap(err, "in marshaller")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = batch.Merge(name, value, pebble.NoSync)
|
err = batch.Merge(name, value, pebble.NoSync)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble set: %w", err)
|
return errors.Wrap(err, "in merge")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := batch.Commit(pebble.NoSync)
|
return errors.Wrap(batch.Commit(pebble.NoSync), "in commit")
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("pebble save commit: %w", err)
|
|
||||||
}
|
|
||||||
batch.Close()
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) LoadChanges(name []byte) ([]change.Change, error) {
|
func (repo *Pebble) LoadChanges(name []byte) ([]change.Change, error) {
|
||||||
|
|
||||||
data, closer, err := repo.db.Get(name)
|
data, closer, err := repo.db.Get(name)
|
||||||
if err != nil && err != pebble.ErrNotFound {
|
if err != nil && err != pebble.ErrNotFound {
|
||||||
return nil, fmt.Errorf("pebble get: %w", err)
|
return nil, errors.Wrapf(err, "in get %s", name) // does returning a name in an error expose too much?
|
||||||
}
|
}
|
||||||
if closer != nil {
|
if closer != nil {
|
||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
|
@ -140,7 +132,7 @@ func unmarshalChanges(name, data []byte) ([]change.Change, error) {
|
||||||
var chg change.Change
|
var chg change.Change
|
||||||
err := dec.Decode(&chg)
|
err := dec.Decode(&chg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("msgpack unmarshal: %w", err)
|
return nil, errors.Wrap(err, "in decode")
|
||||||
}
|
}
|
||||||
chg.Name = name
|
chg.Name = name
|
||||||
changes = append(changes, chg)
|
changes = append(changes, chg)
|
||||||
|
@ -156,24 +148,24 @@ func unmarshalChanges(name, data []byte) ([]change.Change, error) {
|
||||||
|
|
||||||
func (repo *Pebble) DropChanges(name []byte, finalHeight int32) error {
|
func (repo *Pebble) DropChanges(name []byte, finalHeight int32) error {
|
||||||
changes, err := repo.LoadChanges(name)
|
changes, err := repo.LoadChanges(name)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "in load changes for %s", name)
|
||||||
|
}
|
||||||
i := 0
|
i := 0
|
||||||
for ; i < len(changes); i++ {
|
for ; i < len(changes); i++ {
|
||||||
if changes[i].Height > finalHeight {
|
if changes[i].Height > finalHeight {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("pebble drop: %w", err)
|
|
||||||
}
|
|
||||||
// making a performance assumption that DropChanges won't happen often:
|
// making a performance assumption that DropChanges won't happen often:
|
||||||
err = repo.db.Set(name, []byte{}, pebble.NoSync)
|
err = repo.db.Set(name, []byte{}, pebble.NoSync)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble drop: %w", err)
|
return errors.Wrapf(err, "in set at %s", name)
|
||||||
}
|
}
|
||||||
return repo.AppendChanges(changes[:i])
|
return repo.AppendChanges(changes[:i])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) IterateChildren(name []byte, f func(changes []change.Change) bool) {
|
func (repo *Pebble) IterateChildren(name []byte, f func(changes []change.Change) bool) error {
|
||||||
start := make([]byte, len(name)+1) // zeros that last byte; need a constant len for stack alloc?
|
start := make([]byte, len(name)+1) // zeros that last byte; need a constant len for stack alloc?
|
||||||
copy(start, name)
|
copy(start, name)
|
||||||
|
|
||||||
|
@ -195,12 +187,13 @@ func (repo *Pebble) IterateChildren(name []byte, f func(changes []change.Change)
|
||||||
// NOTE! iter.Key() is ephemeral!
|
// NOTE! iter.Key() is ephemeral!
|
||||||
changes, err := unmarshalChanges(iter.Key(), iter.Value())
|
changes, err := unmarshalChanges(iter.Key(), iter.Value())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return errors.Wrapf(err, "from unmarshaller at %s", iter.Key())
|
||||||
}
|
}
|
||||||
if !f(changes) {
|
if !f(changes) {
|
||||||
return
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) IterateAll(predicate func(name []byte) bool) {
|
func (repo *Pebble) IterateAll(predicate func(name []byte) bool) {
|
||||||
|
@ -218,13 +211,10 @@ func (repo *Pebble) Close() error {
|
||||||
|
|
||||||
err := repo.db.Flush()
|
err := repo.db.Flush()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble flush: %w", err)
|
// if we fail to close are we going to try again later?
|
||||||
|
return errors.Wrap(err, "on flush")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
if err != nil {
|
return errors.Wrap(err, "on close")
|
||||||
return fmt.Errorf("pebble close: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/claimtrie/change"
|
"github.com/btcsuite/btcd/claimtrie/change"
|
||||||
"github.com/btcsuite/btcd/claimtrie/param"
|
"github.com/btcsuite/btcd/claimtrie/param"
|
||||||
)
|
)
|
||||||
|
@ -58,7 +56,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nm.normalizedAt = height
|
nm.normalizedAt = height
|
||||||
fmt.Printf("Generating necessary changes for the normalization fork...\n")
|
log.Info("Generating necessary changes for the normalization fork...")
|
||||||
|
|
||||||
// the original code had an unfortunate bug where many unnecessary takeovers
|
// the original code had an unfortunate bug where many unnecessary takeovers
|
||||||
// were triggered at the normalization fork
|
// were triggered at the normalization fork
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Repo interface {
|
||||||
|
|
||||||
// IterateChildren returns change sets for each of name.+
|
// IterateChildren returns change sets for each of name.+
|
||||||
// Return false on f to stop the iteration.
|
// Return false on f to stop the iteration.
|
||||||
IterateChildren(name []byte, f func(changes []change.Change) bool)
|
IterateChildren(name []byte, f func(changes []change.Change) bool) error
|
||||||
|
|
||||||
// IterateAll iterates keys until the predicate function returns false
|
// IterateAll iterates keys until the predicate function returns false
|
||||||
IterateAll(predicate func(name []byte) bool)
|
IterateAll(predicate func(name []byte) bool)
|
||||||
|
|
|
@ -283,37 +283,3 @@ func generateDelayWorkarounds() map[string][]int32 {
|
||||||
"yay-nc-bob-afet-kamera-arkas": {657957},
|
"yay-nc-bob-afet-kamera-arkas": {657957},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var DelayWorkaroundsPart2 = generateDelayWorkaroundsPart2()
|
|
||||||
|
|
||||||
func generateDelayWorkaroundsPart2() map[string][]int32 {
|
|
||||||
return map[string][]int32{
|
|
||||||
"en-vivo-hablando-de-bitcoin-y-3": {664642},
|
|
||||||
"en-vivo-hablando-de-bitcoin-y-4": {664642},
|
|
||||||
"@gn": {752630, 755269},
|
|
||||||
"putalocura": {809590},
|
|
||||||
"@isc": {813832},
|
|
||||||
"@pnl": {864618},
|
|
||||||
"@dreamr": {875433},
|
|
||||||
"2019-10-30": {878258},
|
|
||||||
"papi-16": {884431},
|
|
||||||
"papi-4": {884431},
|
|
||||||
"papi-18": {884431},
|
|
||||||
"papi-17": {884431},
|
|
||||||
"papi-7": {884431},
|
|
||||||
"papi-3": {884431},
|
|
||||||
"papi-30": {884431},
|
|
||||||
"papi": {884431},
|
|
||||||
"papi-9": {884431},
|
|
||||||
"papi-19": {884431},
|
|
||||||
"papi-papi-2": {884431},
|
|
||||||
"papi-6": {884431},
|
|
||||||
"viaje-a-la-luna-": {887018, 887591, 888024},
|
|
||||||
"fortnite1": {900015},
|
|
||||||
"who-is-the-master-": {900787},
|
|
||||||
"thp": {923634},
|
|
||||||
"thm": {923635},
|
|
||||||
"el-presidente": {923766},
|
|
||||||
"@erikh526": {933294},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package temporalrepo
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/cockroachdb/pebble"
|
"github.com/cockroachdb/pebble"
|
||||||
)
|
)
|
||||||
|
@ -15,13 +15,9 @@ type Pebble struct {
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
func NewPebble(path string) (*Pebble, error) {
|
||||||
|
|
||||||
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(128 << 20)})
|
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(128 << 20)})
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("pebble open %s, %w", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := &Pebble{db: db}
|
repo := &Pebble{db: db}
|
||||||
|
|
||||||
return repo, nil
|
return repo, errors.Wrapf(err, "unable to open %s", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) SetNodesAt(name [][]byte, heights []int32) error {
|
func (repo *Pebble) SetNodesAt(name [][]byte, heights []int32) error {
|
||||||
|
@ -38,10 +34,10 @@ func (repo *Pebble) SetNodesAt(name [][]byte, heights []int32) error {
|
||||||
|
|
||||||
err := batch.Set(key.Bytes(), nil, pebble.NoSync)
|
err := batch.Set(key.Bytes(), nil, pebble.NoSync)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble set: %w", err)
|
return errors.Wrap(err, "in set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return batch.Commit(pebble.NoSync)
|
return errors.Wrap(batch.Commit(pebble.NoSync), "in commit")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) NodesAt(height int32) ([][]byte, error) {
|
func (repo *Pebble) NodesAt(height int32) ([][]byte, error) {
|
||||||
|
@ -69,25 +65,17 @@ func (repo *Pebble) NodesAt(height int32) ([][]byte, error) {
|
||||||
names = append(names, name)
|
names = append(names, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := iter.Close()
|
return names, errors.Wrap(iter.Close(), "in close")
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("pebble get: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return names, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Pebble) Close() error {
|
func (repo *Pebble) Close() error {
|
||||||
|
|
||||||
err := repo.db.Flush()
|
err := repo.db.Flush()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pebble fludh: %w", err)
|
// if we fail to close are we going to try again later?
|
||||||
|
return errors.Wrap(err, "on flush")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
if err != nil {
|
return errors.Wrap(err, "on close")
|
||||||
return fmt.Errorf("pebble close: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
14
log.go
14
log.go
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/btcsuite/btcd/addrmgr"
|
"github.com/btcsuite/btcd/addrmgr"
|
||||||
"github.com/btcsuite/btcd/blockchain"
|
"github.com/btcsuite/btcd/blockchain"
|
||||||
"github.com/btcsuite/btcd/blockchain/indexers"
|
"github.com/btcsuite/btcd/blockchain/indexers"
|
||||||
"github.com/btcsuite/btcd/claimtrie"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
"github.com/btcsuite/btcd/connmgr"
|
"github.com/btcsuite/btcd/connmgr"
|
||||||
"github.com/btcsuite/btcd/database"
|
"github.com/btcsuite/btcd/database"
|
||||||
"github.com/btcsuite/btcd/mempool"
|
"github.com/btcsuite/btcd/mempool"
|
||||||
|
@ -59,9 +59,9 @@ var (
|
||||||
amgrLog = backendLog.Logger("AMGR")
|
amgrLog = backendLog.Logger("AMGR")
|
||||||
cmgrLog = backendLog.Logger("CMGR")
|
cmgrLog = backendLog.Logger("CMGR")
|
||||||
bcdbLog = backendLog.Logger("BCDB")
|
bcdbLog = backendLog.Logger("BCDB")
|
||||||
btcdLog = backendLog.Logger("BTCD")
|
btcdLog = backendLog.Logger("MAIN")
|
||||||
chanLog = backendLog.Logger("CHAN")
|
chanLog = backendLog.Logger("CHAN")
|
||||||
clmtLog = backendLog.Logger("CLMT")
|
lbryLog = backendLog.Logger("LBRY")
|
||||||
discLog = backendLog.Logger("DISC")
|
discLog = backendLog.Logger("DISC")
|
||||||
indxLog = backendLog.Logger("INDX")
|
indxLog = backendLog.Logger("INDX")
|
||||||
minrLog = backendLog.Logger("MINR")
|
minrLog = backendLog.Logger("MINR")
|
||||||
|
@ -79,7 +79,7 @@ func init() {
|
||||||
connmgr.UseLogger(cmgrLog)
|
connmgr.UseLogger(cmgrLog)
|
||||||
database.UseLogger(bcdbLog)
|
database.UseLogger(bcdbLog)
|
||||||
blockchain.UseLogger(chanLog)
|
blockchain.UseLogger(chanLog)
|
||||||
claimtrie.UseLogger(clmtLog)
|
node.UseLogger(lbryLog)
|
||||||
indexers.UseLogger(indxLog)
|
indexers.UseLogger(indxLog)
|
||||||
mining.UseLogger(minrLog)
|
mining.UseLogger(minrLog)
|
||||||
cpuminer.UseLogger(minrLog)
|
cpuminer.UseLogger(minrLog)
|
||||||
|
@ -95,9 +95,9 @@ var subsystemLoggers = map[string]btclog.Logger{
|
||||||
"AMGR": amgrLog,
|
"AMGR": amgrLog,
|
||||||
"CMGR": cmgrLog,
|
"CMGR": cmgrLog,
|
||||||
"BCDB": bcdbLog,
|
"BCDB": bcdbLog,
|
||||||
"BTCD": btcdLog,
|
"MAIN": btcdLog,
|
||||||
"CHAN": chanLog,
|
"CHAN": chanLog,
|
||||||
"CLMT": clmtLog,
|
"LBRY": lbryLog,
|
||||||
"DISC": discLog,
|
"DISC": discLog,
|
||||||
"INDX": indxLog,
|
"INDX": indxLog,
|
||||||
"MINR": minrLog,
|
"MINR": minrLog,
|
||||||
|
@ -119,7 +119,7 @@ func initLogRotator(logFile string) {
|
||||||
fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
|
fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
r, err := rotator.New(logFile, 10*1024, false, 3)
|
r, err := rotator.New(logFile, 40*1024, false, 3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
|
fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -59,16 +59,15 @@ func logMemoryUsage() {
|
||||||
|
|
||||||
ds, err := dirSize(cfg.DataDir)
|
ds, err := dirSize(cfg.DataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
btcdLog.Warnf("When reading directory: %s", err.Error())
|
btcdLog.Debugf("When reading directory: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cur := fmt.Sprintf("RAM: using %.1f GB with %.1f available, DISK: using %.1f GB with %.1f available",
|
cur := fmt.Sprintf("RAM: using %.1f GB with %.1f available, DISK: using %.1f GB with %.1f available",
|
||||||
toGB(m2.RSS), toGB(m.Free), toGB(uint64(ds)), toGB(d.Free))
|
toGB(m2.RSS), toGB(m.Available), toGB(uint64(ds)), toGB(d.Free))
|
||||||
if cur != last {
|
if cur != last {
|
||||||
btcdLog.Infof(cur)
|
btcdLog.Infof(cur)
|
||||||
last = cur
|
last = cur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2735,19 +2735,19 @@ func newServer(listenAddrs, agentBlacklist, agentWhitelist []string,
|
||||||
switch cfg.ClaimTrieImpl {
|
switch cfg.ClaimTrieImpl {
|
||||||
case "none":
|
case "none":
|
||||||
// Disable ClaimTrie for development purpose.
|
// Disable ClaimTrie for development purpose.
|
||||||
clmtLog.Infof("ClaimTrie is disabled")
|
lbryLog.Infof("ClaimTrie is disabled")
|
||||||
default:
|
default:
|
||||||
ct, err = claimtrie.New(claimTrieCfg)
|
ct, err = claimtrie.New(claimTrieCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if h := cfg.ClaimTrieHeight; h != 0 {
|
if h := cfg.ClaimTrieHeight; h != 0 {
|
||||||
clmtLog.Infof("Reseting height to %d", h)
|
lbryLog.Infof("Reseting height to %d", h)
|
||||||
err := ct.ResetHeight(int32(h))
|
err := ct.ResetHeight(int32(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
clmtLog.Infof("Height is reset to %d", h)
|
lbryLog.Infof("Height is reset to %d", h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue