Repository: decred/dcrd
Pull request #2507 (2020-12-13 06:44:22)

blockchain: Explicit hash in max block size func.
This modifies `MaxBlockSize` to accept a hash instead of using the current chain tip as part of an overall effort to make the blockchain module more explicit and less reliant on the current state.


Patch:
diff --git a/blockchain/chain.go b/blockchain/chain.go
index 2e53223e..2f1bd924 100644
--- a/blockchain/chain.go
+++ b/blockchain/chain.go
@@ -1566,12 +1566,22 @@ func (b *BlockChain) maxBlockSize(prevNode *blockNode) (int64, error) {
 }
 
 // MaxBlockSize returns the maximum permitted block size for the block AFTER
-// the end of the current best chain.
+// the provided block hash.
 //
 // This function is safe for concurrent access.
-func (b *BlockChain) MaxBlockSize() (int64, error) {
+func (b *BlockChain) MaxBlockSize(hash *chainhash.Hash) (int64, error) {
+	// NOTE: The requirement for the node being fully validated here is strictly
+	// stronger than what is actually required.  In reality, all that is needed
+	// is for the block data for the node and all of its ancestors to be
+	// available, but there is not currently any tracking to be able to
+	// efficiently determine that state.
+	node := b.index.LookupNode(hash)
+	if node == nil || !b.index.NodeStatus(node).HasValidated() {
+		return 0, unknownBlockError(hash)
+	}
+
 	b.chainLock.Lock()
-	maxSize, err := b.maxBlockSize(b.bestChain.Tip())
+	maxSize, err := b.maxBlockSize(node)
 	b.chainLock.Unlock()
 	return maxSize, err
 }
diff --git a/internal/rpcserver/interface.go b/internal/rpcserver/interface.go
index 4319bca6..0fb6d7d1 100644
--- a/internal/rpcserver/interface.go
+++ b/internal/rpcserver/interface.go
@@ -371,8 +371,8 @@ type Chain interface {
 	MainChainHasBlock(hash *chainhash.Hash) bool
 
 	// MaxBlockSize returns the maximum permitted block size for the block AFTER
-	// the end of the current best chain.
-	MaxBlockSize() (int64, error)
+	// the provided block hash.
+	MaxBlockSize(hash *chainhash.Hash) (int64, error)
 
 	// MissedTickets returns all currently missed tickets.
 	MissedTickets() ([]chainhash.Hash, error)
diff --git a/internal/rpcserver/rpcserver.go b/internal/rpcserver/rpcserver.go
index fcf3ece0..9073d078 100644
--- a/internal/rpcserver/rpcserver.go
+++ b/internal/rpcserver/rpcserver.go
@@ -2033,7 +2033,7 @@ func handleGetBlockchainInfo(_ context.Context, s *Server, cmd interface{}) (int
 	}
 
 	// Fetch the maximum allowed block size.
-	maxBlockSize, err := chain.MaxBlockSize()
+	maxBlockSize, err := chain.MaxBlockSize(&best.PrevHash)
 	if err != nil {
 		return nil, rpcInternalError(err.Error(),
 			"Could not fetch max block size.")


Test patch:
diff --git a/internal/rpcserver/rpcserverhandlers_test.go b/internal/rpcserver/rpcserverhandlers_test.go
index ac0da0e3..56715734 100644
--- a/internal/rpcserver/rpcserverhandlers_test.go
+++ b/internal/rpcserver/rpcserverhandlers_test.go
@@ -343,8 +343,8 @@ func (c *testRPCChain) MainChainHasBlock(hash *chainhash.Hash) bool {
 }
 
 // MaxBlockSize returns a mocked maximum permitted block size for the block
-// AFTER the end of the current best chain.
-func (c *testRPCChain) MaxBlockSize() (int64, error) {
+// AFTER the provided block hash.
+func (c *testRPCChain) MaxBlockSize(hash *chainhash.Hash) (int64, error) {
 	return c.maxBlockSize, c.maxBlockSizeErr
 }