Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blockchain: Return uint256 from chain work method. #2959

Merged
merged 1 commit into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions internal/blockchain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"context"
"errors"
"fmt"
"math/big"
"sync"
"time"

Expand Down Expand Up @@ -463,13 +462,13 @@ func (b *BlockChain) HaveBlock(hash *chainhash.Hash) bool {

// ChainWork returns the total work up to and including the block of the
// provided block hash.
func (b *BlockChain) ChainWork(hash *chainhash.Hash) (*big.Int, error) {
func (b *BlockChain) ChainWork(hash *chainhash.Hash) (uint256.Uint256, error) {
node := b.index.LookupNode(hash)
if node == nil {
return nil, unknownBlockError(hash)
return uint256.Uint256{}, unknownBlockError(hash)
}

return node.workSum.ToBig(), nil
return node.workSum, nil
}

// TipGeneration returns the entire generation of blocks stemming from the
Expand Down
25 changes: 22 additions & 3 deletions internal/netsync/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/decred/dcrd/internal/blockchain"
"github.com/decred/dcrd/internal/mempool"
"github.com/decred/dcrd/internal/progresslog"
"github.com/decred/dcrd/math/uint256"
peerpkg "github.com/decred/dcrd/peer/v3"
"github.com/decred/dcrd/wire"
)
Expand Down Expand Up @@ -272,6 +273,14 @@ type SyncManager struct {
// creation time and treated as immutable after that.
cfg Config

// minKnownWork houses the minimum known work from the associated network
// params converted to a uint256 so the conversion only needs to be
// performed once when the sync manager is initialized. Ideally, the chain
// params should be updated to use the new type, but that will be a major
// version bump, so a one-time conversion is a good tradeoff in the mean
// time.
minKnownWork *uint256.Uint256

rejectedTxns *apbf.Filter
requestedTxns map[chainhash.Hash]struct{}
requestedBlocks map[chainhash.Hash]struct{}
Expand Down Expand Up @@ -1094,10 +1103,9 @@ func (m *SyncManager) handleHeadersMsg(hmsg *headersMsg) {
isChainCurrent := chain.IsCurrent()
receivedMaxHeaders := len(headers) == wire.MaxBlockHeadersPerMsg
if !isChainCurrent && !peer.Inbound() && !receivedMaxHeaders {
minKnownWork := m.cfg.ChainParams.MinKnownChainWork
if minKnownWork != nil {
if m.minKnownWork != nil {
workSum, err := chain.ChainWork(finalReceivedHash)
if err == nil && workSum.Cmp(minKnownWork) < 0 {
if err == nil && workSum.Lt(m.minKnownWork) {
log.Debugf("Best known chain for peer %s has too little "+
"cumulative work -- disconnecting", peer)
peer.Disconnect()
Expand Down Expand Up @@ -1771,12 +1779,23 @@ type Config struct {
// New returns a new network chain synchronization manager. Use Run to begin
// processing asynchronous events.
func New(config *Config) *SyncManager {
// Convert the minimum known work to a uint256 when it exists. Ideally, the
// chain params should be updated to use the new type, but that will be a
// major version bump, so a one-time conversion is a good tradeoff in the
// mean time.
var minKnownWork *uint256.Uint256
minKnownWorkBig := config.ChainParams.MinKnownChainWork
if minKnownWorkBig != nil {
minKnownWork = new(uint256.Uint256).SetBig(minKnownWorkBig)
}

return &SyncManager{
cfg: *config,
rejectedTxns: apbf.NewFilter(maxRejectedTxns, rejectedTxnsFPRate),
requestedTxns: make(map[chainhash.Hash]struct{}),
requestedBlocks: make(map[chainhash.Hash]struct{}),
peers: make(map[*peerpkg.Peer]*syncMgrPeer),
minKnownWork: minKnownWork,
hdrSyncState: makeHeaderSyncState(),
progressLogger: progresslog.New("Processed", log),
msgChan: make(chan interface{}, config.MaxPeers*3),
Expand Down
4 changes: 2 additions & 2 deletions internal/rpcserver/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package rpcserver

import (
"context"
"math/big"
"net"
"time"

Expand All @@ -19,6 +18,7 @@ import (
"github.com/decred/dcrd/internal/blockchain/indexers"
"github.com/decred/dcrd/internal/mempool"
"github.com/decred/dcrd/internal/mining"
"github.com/decred/dcrd/math/uint256"
"github.com/decred/dcrd/peer/v3"
"github.com/decred/dcrd/rpc/jsonrpc/types/v4"
"github.com/decred/dcrd/txscript/v4/stdaddr"
Expand Down Expand Up @@ -246,7 +246,7 @@ type Chain interface {

// ChainWork returns the total work up to and including the block of the
// provided block hash.
ChainWork(hash *chainhash.Hash) (*big.Int, error)
ChainWork(hash *chainhash.Hash) (uint256.Uint256, error)

// CheckLiveTicket returns whether or not a ticket exists in the live ticket
// treap of the best node.
Expand Down
35 changes: 22 additions & 13 deletions internal/rpcserver/rpcserverhandlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/decred/dcrd/internal/mempool"
"github.com/decred/dcrd/internal/mining"
"github.com/decred/dcrd/internal/version"
"github.com/decred/dcrd/math/uint256"
"github.com/decred/dcrd/peer/v3"
"github.com/decred/dcrd/rpc/jsonrpc/types/v4"
"github.com/decred/dcrd/txscript/v4"
Expand Down Expand Up @@ -144,7 +145,7 @@ type testRPCChain struct {
blockHeightByHashErr error
calcWantHeight int64
chainTips []blockchain.ChainTipInfo
chainWork *big.Int
chainWork uint256.Uint256
chainWorkErr error
checkLiveTicket bool
checkLiveTickets []bool
Expand Down Expand Up @@ -241,7 +242,7 @@ func (c *testRPCChain) ChainTips() []blockchain.ChainTipInfo {

// ChainWork returns returns a mocked total work up to and including the block
// of the provided block hash.
func (c *testRPCChain) ChainWork(hash *chainhash.Hash) (*big.Int, error) {
func (c *testRPCChain) ChainWork(hash *chainhash.Hash) (uint256.Uint256, error) {
return c.chainWork, c.chainWorkErr
}

Expand Down Expand Up @@ -1272,6 +1273,19 @@ func hexToBytes(s string) []byte {
return b
}

// hexToUint256 interprets the passed hex string as a 256-bit big-endian
// unsigned integer and returns the resulting uint256. It will panic if there
// is an error. This is only provided for the hard-coded constants so errors in
// the source code can be detected. It will only (and must only) be called with
// hard-coded values.
func hexToUint256(s string) uint256.Uint256 {
b, err := hex.DecodeString(s)
if err != nil {
panic("invalid hex in source file: " + s)
}
return *new(uint256.Uint256).SetByteSlice(b)
}

// hexToMsgTx converts the passed hex string into a wire.MsgTx and will panic if
// there is an error. This is only provided for hard-coded constants so errors
// in the source code can be detected. It will only (and must only) be called
Expand Down Expand Up @@ -1416,7 +1430,7 @@ func defaultMockRPCChain() *testRPCChain {
headerByHashFn := func() wire.BlockHeader { return blkHeader }
blkHash := blk.Hash()
blkHeight := blk.Height()
chainWork, _ := new(big.Int).SetString("0e805fb85284503581c57c", 16)
chainWork := hexToUint256("0e805fb85284503581c57c")
return &testRPCChain{
bestSnapshot: &blockchain.BestState{
Hash: *blkHash,
Expand Down Expand Up @@ -3579,8 +3593,7 @@ func TestHandleGetBlockchainInfo(t *testing.T) {
}
chain.bestHeaderHash = *hash
chain.bestHeaderHeight = 463073
chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
chain.chainWork = hexToUint256("115d2833849090b0026506")
chain.isCurrent = false
chain.maxBlockSize = 393216
chain.stateLastChangedHeight = int64(149248)
Expand Down Expand Up @@ -3619,8 +3632,7 @@ func TestHandleGetBlockchainInfo(t *testing.T) {
Hash: *genesisHash,
PrevHash: *genesisPrevHash,
}
chain.chainWork = big.NewInt(0).SetBytes([]byte{0x80, 0x00, 0x40, 0x00, 0x20,
0x00})
chain.chainWork = hexToUint256("800040002000")
chain.isCurrent = false
chain.maxBlockSize = 393216
chain.nextThresholdState = blockchain.ThresholdStateTuple{
Expand Down Expand Up @@ -3681,8 +3693,7 @@ func TestHandleGetBlockchainInfo(t *testing.T) {
Hash: *hash,
PrevHash: *prevHash,
}
chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
chain.chainWork = hexToUint256("115d2833849090b0026506")
chain.maxBlockSizeErr = errors.New("could not fetch max block size")
return chain
}(),
Expand All @@ -3700,8 +3711,7 @@ func TestHandleGetBlockchainInfo(t *testing.T) {
Hash: *hash,
PrevHash: *prevHash,
}
chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
chain.chainWork = hexToUint256("115d2833849090b0026506")
chain.maxBlockSize = 393216
chain.nextThresholdStateErr = errors.New("could not fetch threshold state")
return chain
Expand All @@ -3720,8 +3730,7 @@ func TestHandleGetBlockchainInfo(t *testing.T) {
Hash: *hash,
PrevHash: *prevHash,
}
chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
chain.chainWork = hexToUint256("115d2833849090b0026506")
chain.maxBlockSize = 393216
chain.stateLastChangedHeightErr = errors.New("could not fetch state last changed")
return chain
Expand Down