mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-21 14:26:45 +00:00
214 lines
6.2 KiB
Go
214 lines
6.2 KiB
Go
package consensus
|
|
|
|
import (
|
|
"encoding/json"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
|
"github.com/kaspanet/kaspad/domain/dagconfig"
|
|
"github.com/kaspanet/kaspad/infrastructure/db/database"
|
|
"github.com/pkg/errors"
|
|
"io"
|
|
)
|
|
|
|
type testConsensus struct {
|
|
*consensus
|
|
dagParams *dagconfig.Params
|
|
database database.Database
|
|
|
|
testBlockBuilder testapi.TestBlockBuilder
|
|
testReachabilityManager testapi.TestReachabilityManager
|
|
testConsensusStateManager testapi.TestConsensusStateManager
|
|
testTransactionValidator testapi.TestTransactionValidator
|
|
}
|
|
|
|
func (tc *testConsensus) DAGParams() *dagconfig.Params {
|
|
return tc.dagParams
|
|
}
|
|
|
|
func (tc *testConsensus) BuildBlockWithParents(parentHashes []*externalapi.DomainHash,
|
|
coinbaseData *externalapi.DomainCoinbaseData, transactions []*externalapi.DomainTransaction) (
|
|
*externalapi.DomainBlock, model.UTXODiff, error) {
|
|
|
|
// Require write lock because BuildBlockWithParents stages temporary data
|
|
tc.lock.Lock()
|
|
defer tc.lock.Unlock()
|
|
|
|
block, diff, err := tc.testBlockBuilder.BuildBlockWithParents(parentHashes, coinbaseData, transactions)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return block, diff, nil
|
|
}
|
|
|
|
func (tc *testConsensus) AddBlock(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData,
|
|
transactions []*externalapi.DomainTransaction) (*externalapi.DomainHash, *externalapi.BlockInsertionResult, error) {
|
|
|
|
// Require write lock because BuildBlockWithParents stages temporary data
|
|
tc.lock.Lock()
|
|
defer tc.lock.Unlock()
|
|
|
|
block, _, err := tc.testBlockBuilder.BuildBlockWithParents(parentHashes, coinbaseData, transactions)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
blockInsertionResult, err := tc.blockProcessor.ValidateAndInsertBlock(block)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return consensushashing.BlockHash(block), blockInsertionResult, nil
|
|
}
|
|
|
|
func (tc *testConsensus) AddUTXOInvalidHeader(parentHashes []*externalapi.DomainHash) (*externalapi.DomainHash,
|
|
*externalapi.BlockInsertionResult, error) {
|
|
|
|
// Require write lock because BuildBlockWithParents stages temporary data
|
|
tc.lock.Lock()
|
|
defer tc.lock.Unlock()
|
|
|
|
header, err := tc.testBlockBuilder.BuildUTXOInvalidHeader(parentHashes)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
blockInsertionResult, err := tc.blockProcessor.ValidateAndInsertBlock(&externalapi.DomainBlock{
|
|
Header: header,
|
|
Transactions: nil,
|
|
})
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return consensushashing.HeaderHash(header), blockInsertionResult, nil
|
|
}
|
|
|
|
func (tc *testConsensus) AddUTXOInvalidBlock(parentHashes []*externalapi.DomainHash) (*externalapi.DomainHash,
|
|
*externalapi.BlockInsertionResult, error) {
|
|
|
|
// Require write lock because BuildBlockWithParents stages temporary data
|
|
tc.lock.Lock()
|
|
defer tc.lock.Unlock()
|
|
|
|
block, err := tc.testBlockBuilder.BuildUTXOInvalidBlock(parentHashes)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
blockInsertionResult, err := tc.blockProcessor.ValidateAndInsertBlock(block)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return consensushashing.BlockHash(block), blockInsertionResult, nil
|
|
}
|
|
|
|
func (tc *testConsensus) MineJSON(r io.Reader, blockType testapi.MineJSONBlockType) (tips []*externalapi.DomainHash, err error) {
|
|
// jsonBlock is a json representation of a block in mine format
|
|
type jsonBlock struct {
|
|
ID string `json:"id"`
|
|
Parents []string `json:"parents"`
|
|
}
|
|
|
|
tipSet := map[externalapi.DomainHash]*externalapi.DomainHash{}
|
|
tipSet[*tc.dagParams.GenesisHash] = tc.dagParams.GenesisHash
|
|
|
|
parentsMap := make(map[string]*externalapi.DomainHash)
|
|
parentsMap["0"] = tc.dagParams.GenesisHash
|
|
|
|
decoder := json.NewDecoder(r)
|
|
// read open bracket
|
|
_, err = decoder.Token()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// while the array contains values
|
|
for decoder.More() {
|
|
var block jsonBlock
|
|
// decode an array value (Message)
|
|
err := decoder.Decode(&block)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if block.ID == "0" {
|
|
continue
|
|
}
|
|
parentHashes := make([]*externalapi.DomainHash, len(block.Parents))
|
|
var ok bool
|
|
for i, parentID := range block.Parents {
|
|
parentHashes[i], ok = parentsMap[parentID]
|
|
if !ok {
|
|
return nil, errors.Errorf("Couldn't find blockID: %s", parentID)
|
|
}
|
|
delete(tipSet, *parentHashes[i])
|
|
}
|
|
|
|
var blockHash *externalapi.DomainHash
|
|
switch blockType {
|
|
case testapi.MineJSONBlockTypeUTXOValidBlock:
|
|
blockHash, _, err = tc.AddBlock(parentHashes, nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
case testapi.MineJSONBlockTypeUTXOInvalidBlock:
|
|
blockHash, _, err = tc.AddUTXOInvalidBlock(parentHashes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
case testapi.MineJSONBlockTypeUTXOInvalidHeader:
|
|
blockHash, _, err = tc.AddUTXOInvalidHeader(parentHashes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
default:
|
|
return nil, errors.Errorf("unknwon block type %v", blockType)
|
|
}
|
|
|
|
parentsMap[block.ID] = blockHash
|
|
tipSet[*blockHash] = blockHash
|
|
}
|
|
|
|
tips = make([]*externalapi.DomainHash, len(tipSet))
|
|
i := 0
|
|
for _, v := range tipSet {
|
|
tips[i] = v
|
|
i++
|
|
}
|
|
return tips, nil
|
|
}
|
|
|
|
func (tc *testConsensus) BuildUTXOInvalidBlock(parentHashes []*externalapi.DomainHash) (*externalapi.DomainBlock, error) {
|
|
// Require write lock because BuildBlockWithParents stages temporary data
|
|
tc.lock.Lock()
|
|
defer tc.lock.Unlock()
|
|
|
|
return tc.testBlockBuilder.BuildUTXOInvalidBlock(parentHashes)
|
|
}
|
|
|
|
func (tc *testConsensus) BuildHeaderWithParents(parentHashes []*externalapi.DomainHash) (externalapi.BlockHeader, error) {
|
|
// Require write lock because BuildUTXOInvalidHeader stages temporary data
|
|
tc.lock.Lock()
|
|
defer tc.lock.Unlock()
|
|
|
|
return tc.testBlockBuilder.BuildUTXOInvalidHeader(parentHashes)
|
|
}
|
|
|
|
func (tc *testConsensus) DiscardAllStores() {
|
|
tc.AcceptanceDataStore().Discard()
|
|
tc.BlockHeaderStore().Discard()
|
|
tc.BlockRelationStore().Discard()
|
|
tc.BlockStatusStore().Discard()
|
|
tc.BlockStore().Discard()
|
|
tc.ConsensusStateStore().Discard()
|
|
tc.GHOSTDAGDataStore().Discard()
|
|
tc.HeaderTipsStore().Discard()
|
|
tc.MultisetStore().Discard()
|
|
tc.PruningStore().Discard()
|
|
tc.ReachabilityDataStore().Discard()
|
|
tc.UTXODiffStore().Discard()
|
|
tc.HeadersSelectedChainStore().Discard()
|
|
}
|