mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-09-13 13:00:10 +00:00

* [NOD-1406] Remove mempool UTXO diff * [NOD-1406] Fix mempool tests * [NOD-1406] Fetch mempool transactions before locking the dag in NewBlockTemplate * [NOD-1406] Remove redundant comment * [NOD-1406] Move mempool UTXO set to a different file * [NOD-1406] Fix transactionRelatedUTXOEntries receiver's name * [NOD-1406] Fix variable names and fix comments * [NOD-1406] Rename inputsWithUTXOEntries->referencedUTXOEntries * [NOD-1406] Remove debug logs
119 lines
3.6 KiB
Go
119 lines
3.6 KiB
Go
package rpchandlers
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"github.com/kaspanet/kaspad/app/appmessage"
|
|
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
"github.com/kaspanet/kaspad/util"
|
|
"github.com/kaspanet/kaspad/util/daghash"
|
|
)
|
|
|
|
const (
|
|
// maxBlocksInGetBlocksResponse is the max amount of blocks that are
|
|
// allowed in a GetBlocksResult.
|
|
maxBlocksInGetBlocksResponse = 100
|
|
)
|
|
|
|
// HandleGetBlocks handles the respectively named RPC command
|
|
func HandleGetBlocks(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
getBlocksRequest := request.(*appmessage.GetBlocksRequestMessage)
|
|
|
|
var lowHash *daghash.Hash
|
|
if getBlocksRequest.LowHash != "" {
|
|
lowHash = &daghash.Hash{}
|
|
err := daghash.Decode(lowHash, getBlocksRequest.LowHash)
|
|
if err != nil {
|
|
errorMessage := &appmessage.GetBlocksResponseMessage{}
|
|
errorMessage.Error = appmessage.RPCErrorf("Could not parse lowHash: %s", err)
|
|
return errorMessage, nil
|
|
}
|
|
}
|
|
|
|
context.DAG.RLock()
|
|
defer context.DAG.RUnlock()
|
|
|
|
// If lowHash is not in the DAG, there's nothing to do; return an error.
|
|
if lowHash != nil && !context.DAG.IsKnownBlock(lowHash) {
|
|
errorMessage := &appmessage.GetBlocksResponseMessage{}
|
|
errorMessage.Error = appmessage.RPCErrorf("Block %s not found in DAG", lowHash)
|
|
return errorMessage, nil
|
|
}
|
|
|
|
// Retrieve the block hashes.
|
|
blockHashes, err := context.DAG.BlockHashesFrom(lowHash, maxBlocksInGetBlocksResponse)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Convert the hashes to strings
|
|
hashes := make([]string, len(blockHashes))
|
|
for i, blockHash := range blockHashes {
|
|
hashes[i] = blockHash.String()
|
|
}
|
|
|
|
// Include more data if requested
|
|
var blockHexes []string
|
|
var blockVerboseData []*appmessage.BlockVerboseData
|
|
if getBlocksRequest.IncludeBlockHexes || getBlocksRequest.IncludeBlockVerboseData {
|
|
blockBytesSlice, err := hashesToBlockBytes(context, blockHashes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if getBlocksRequest.IncludeBlockHexes {
|
|
blockHexes = blockBytesToStrings(blockBytesSlice)
|
|
}
|
|
if getBlocksRequest.IncludeBlockVerboseData {
|
|
data, err := blockBytesToBlockVerboseResults(context, blockBytesSlice, getBlocksRequest.IncludeBlockVerboseData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blockVerboseData = data
|
|
}
|
|
}
|
|
|
|
response := appmessage.NewGetBlocksResponseMessage(hashes, blockHexes, blockVerboseData)
|
|
return response, nil
|
|
}
|
|
|
|
func hashesToBlockBytes(context *rpccontext.Context, hashes []*daghash.Hash) ([][]byte, error) {
|
|
blocks := make([][]byte, len(hashes))
|
|
for i, hash := range hashes {
|
|
block, err := context.DAG.BlockByHash(hash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blockBytes, err := block.Bytes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blocks[i] = blockBytes
|
|
}
|
|
return blocks, nil
|
|
}
|
|
func blockBytesToStrings(blockBytesSlice [][]byte) []string {
|
|
rawBlocks := make([]string, len(blockBytesSlice))
|
|
for i, blockBytes := range blockBytesSlice {
|
|
rawBlocks[i] = hex.EncodeToString(blockBytes)
|
|
}
|
|
return rawBlocks
|
|
}
|
|
|
|
func blockBytesToBlockVerboseResults(context *rpccontext.Context, blockBytesSlice [][]byte,
|
|
includeTransactionVerboseData bool) ([]*appmessage.BlockVerboseData, error) {
|
|
|
|
verboseBlocks := make([]*appmessage.BlockVerboseData, len(blockBytesSlice))
|
|
for i, blockBytes := range blockBytesSlice {
|
|
block, err := util.NewBlockFromBytes(blockBytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
getBlockVerboseResult, err := context.BuildBlockVerboseData(block, includeTransactionVerboseData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
verboseBlocks[i] = getBlockVerboseResult
|
|
}
|
|
return verboseBlocks, nil
|
|
}
|