Skip to content

Commit

Permalink
main: Add invalidateblock and reconsiderblock rpc commands
Browse files Browse the repository at this point in the history
The rpc calls and the rpchelp is added for the invalidateblock
and reconsiderblock methods on BlockChain.
  • Loading branch information
kcalvinalvin authored and Crypt-iQ committed Jun 19, 2024
1 parent 1cb4d3a commit 0aa80ea
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
35 changes: 35 additions & 0 deletions rpcclient/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1419,3 +1419,38 @@ func (c *Client) GetDescriptorInfoAsync(descriptor string) FutureGetDescriptorIn
func (c *Client) GetDescriptorInfo(descriptor string) (*btcjson.GetDescriptorInfoResult, error) {
return c.GetDescriptorInfoAsync(descriptor).Receive()
}

// FutureReconsiderBlockResult is a future promise to deliver the result of a
// ReconsiderBlockAsync RPC invocation (or an applicable error).
type FutureReconsiderBlockResult chan *Response

// Receive waits for the Response promised by the future and returns the raw
// block requested from the server given its hash.
func (r FutureReconsiderBlockResult) Receive() error {
_, err := ReceiveFuture(r)
return err
}

// ReconsiderBlockAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See ReconsiderBlock for the blocking version and more details.
func (c *Client) ReconsiderBlockAsync(
blockHash *chainhash.Hash) FutureReconsiderBlockResult {

hash := ""
if blockHash != nil {
hash = blockHash.String()
}

cmd := btcjson.NewReconsiderBlockCmd(hash)
return c.SendCmd(cmd)
}

// ReconsiderBlock reconsiders an verifies a specific block and the branch that
// the block is included in. If the block is valid on reconsideration, the chain
// will reorg to that block if it has more PoW than the current tip.
func (c *Client) ReconsiderBlock(blockHash *chainhash.Hash) error {
return c.ReconsiderBlockAsync(blockHash).Receive()
}
40 changes: 38 additions & 2 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,10 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
"getrawtransaction": handleGetRawTransaction,
"gettxout": handleGetTxOut,
"help": handleHelp,
"invalidateblock": handleInvalidateBlock,
"node": handleNode,
"ping": handlePing,
"reconsiderblock": handleReconsiderBlock,
"searchrawtransactions": handleSearchRawTransactions,
"sendrawtransaction": handleSendRawTransaction,
"setgenerate": handleSetGenerate,
Expand Down Expand Up @@ -241,9 +243,7 @@ var rpcUnimplemented = map[string]struct{}{
"getmempoolentry": {},
"getnetworkinfo": {},
"getwork": {},
"invalidateblock": {},
"preciousblock": {},
"reconsiderblock": {},
}

// Commands that are available to a limited user
Expand Down Expand Up @@ -284,6 +284,8 @@ var rpcLimited = map[string]struct{}{
"getrawmempool": {},
"getrawtransaction": {},
"gettxout": {},
"invalidateblock": {},
"reconsiderblock": {},
"searchrawtransactions": {},
"sendrawtransaction": {},
"submitblock": {},
Expand Down Expand Up @@ -2850,6 +2852,23 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i
return txOutReply, nil
}

// handleInvalidateBlock implements the invalidateblock command.
func handleInvalidateBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*btcjson.InvalidateBlockCmd)

invalidateHash, err := chainhash.NewHashFromStr(c.BlockHash)
if err != nil {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCDeserialization,
Message: fmt.Sprintf("Failed to deserialize blockhash from string of %s",
invalidateHash),
}
}

err = s.cfg.Chain.InvalidateBlock(invalidateHash)
return nil, err
}

// handleHelp implements the help command.
func handleHelp(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*btcjson.HelpCmd)
Expand Down Expand Up @@ -3123,6 +3142,23 @@ func fetchMempoolTxnsForAddress(s *rpcServer, addr btcutil.Address, numToSkip, n
return mpTxns[numToSkip:rangeEnd], numToSkip
}

// handleReconsiderBlock implements the reconsiderblock command.
func handleReconsiderBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*btcjson.ReconsiderBlockCmd)

reconsiderHash, err := chainhash.NewHashFromStr(c.BlockHash)
if err != nil {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCDeserialization,
Message: fmt.Sprintf("Failed to deserialize blockhash from string of %s",
reconsiderHash),
}
}

err = s.cfg.Chain.ReconsiderBlock(reconsiderHash)
return nil, err
}

// handleSearchRawTransactions implements the searchrawtransactions command.
func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
// Respond with an error if the address index is not enabled.
Expand Down
10 changes: 10 additions & 0 deletions rpcserverhelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,10 @@ var helpDescsEnUS = map[string]string{
"gettxout-vout": "The index of the output",
"gettxout-includemempool": "Include the mempool when true",

// InvalidateBlockCmd help.
"invalidateblock--synopsis": "Invalidates the block of the given block hash. To re-validate the invalidated block, use the reconsiderblock rpc",
"invalidateblock-blockhash": "The block hash of the block to invalidate",

// HelpCmd help.
"help--synopsis": "Returns a list of all commands or help for a specified command.",
"help-command": "The command to retrieve help for",
Expand Down Expand Up @@ -681,6 +685,10 @@ var helpDescsEnUS = map[string]string{
"loadtxfilter-addresses": "Array of addresses to add to the transaction filter",
"loadtxfilter-outpoints": "Array of outpoints to add to the transaction filter",

// ReconsiderBlockCmd help.
"reconsiderblock--synopsis": "Reconsiders the block of the given block hash. Can be used to re-validate blocks invalidated with invalidateblock",
"reconsiderblock-blockhash": "The block hash of the block to reconsider",

// Rescan help.
"rescan--synopsis": "Rescan block chain for transactions to addresses.\n" +
"When the endblock parameter is omitted, the rescan continues through the best block in the main chain.\n" +
Expand Down Expand Up @@ -788,7 +796,9 @@ var rpcResultTypes = map[string][]interface{}{
"gettxout": {(*btcjson.GetTxOutResult)(nil)},
"node": nil,
"help": {(*string)(nil), (*string)(nil)},
"invalidateblock": nil,
"ping": nil,
"reconsiderblock": nil,
"searchrawtransactions": {(*string)(nil), (*[]btcjson.SearchRawTransactionsResult)(nil)},
"sendrawtransaction": {(*string)(nil)},
"setgenerate": nil,
Expand Down

0 comments on commit 0aa80ea

Please sign in to comment.