mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-26 05:10:02 +00:00
Compare commits
6 Commits
v0.10.0-al
...
v0.9.1-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e457503aea | ||
|
|
c6c63c7ff9 | ||
|
|
dd91ffb7d8 | ||
|
|
921ca19b42 | ||
|
|
98c2dc8189 | ||
|
|
37654156a6 |
3
.github/workflows/go.yml
vendored
3
.github/workflows/go.yml
vendored
@@ -63,9 +63,6 @@ jobs:
|
||||
with:
|
||||
go-version: 1.16
|
||||
|
||||
- name: Delete the stability tests from coverage
|
||||
run: rm -r stability-tests
|
||||
|
||||
- name: Create coverage file
|
||||
run: go test -v -covermode=atomic -coverpkg=./... -coverprofile coverage.txt ./...
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ $ kaspad
|
||||
```
|
||||
|
||||
## Discord
|
||||
Join our discord server using the following link: https://discord.gg/YNYnNN5Pf2
|
||||
Join our discord server using the following link: https://discord.gg/WmGhhzk
|
||||
|
||||
## Issue Tracker
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ func doUpgrades() error {
|
||||
|
||||
// dbPath returns the path to the block database given a database type.
|
||||
func databasePath(cfg *config.Config) string {
|
||||
return filepath.Join(cfg.AppDir, "data")
|
||||
return filepath.Join(cfg.DataDir, "db")
|
||||
}
|
||||
|
||||
func removeDatabase(cfg *config.Config) error {
|
||||
|
||||
@@ -83,6 +83,7 @@ func DomainTransactionToMsgTx(domainTransaction *externalapi.DomainTransaction)
|
||||
LockTime: domainTransaction.LockTime,
|
||||
SubnetworkID: domainTransaction.SubnetworkID,
|
||||
Gas: domainTransaction.Gas,
|
||||
PayloadHash: domainTransaction.PayloadHash,
|
||||
Payload: domainTransaction.Payload,
|
||||
}
|
||||
}
|
||||
@@ -132,6 +133,7 @@ func MsgTxToDomainTransaction(msgTx *MsgTx) *externalapi.DomainTransaction {
|
||||
LockTime: msgTx.LockTime,
|
||||
SubnetworkID: msgTx.SubnetworkID,
|
||||
Gas: msgTx.Gas,
|
||||
PayloadHash: msgTx.PayloadHash,
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
@@ -196,6 +198,10 @@ func RPCTransactionToDomainTransaction(rpcTransaction *RPCTransaction) (*externa
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadHash, err := externalapi.NewDomainHashFromString(rpcTransaction.PayloadHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload, err := hex.DecodeString(rpcTransaction.Payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -208,6 +214,7 @@ func RPCTransactionToDomainTransaction(rpcTransaction *RPCTransaction) (*externa
|
||||
LockTime: rpcTransaction.LockTime,
|
||||
SubnetworkID: *subnetworkID,
|
||||
Gas: rpcTransaction.LockTime,
|
||||
PayloadHash: *payloadHash,
|
||||
Payload: payload,
|
||||
}, nil
|
||||
}
|
||||
@@ -237,6 +244,7 @@ func DomainTransactionToRPCTransaction(transaction *externalapi.DomainTransactio
|
||||
}
|
||||
}
|
||||
subnetworkID := transaction.SubnetworkID.String()
|
||||
payloadHash := transaction.PayloadHash.String()
|
||||
payload := hex.EncodeToString(transaction.Payload)
|
||||
return &RPCTransaction{
|
||||
Version: transaction.Version,
|
||||
@@ -245,6 +253,7 @@ func DomainTransactionToRPCTransaction(transaction *externalapi.DomainTransactio
|
||||
LockTime: transaction.LockTime,
|
||||
SubnetworkID: subnetworkID,
|
||||
Gas: transaction.LockTime,
|
||||
PayloadHash: payloadHash,
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
@@ -265,7 +274,7 @@ func OutpointAndUTXOEntryPairsToDomainOutpointAndUTXOEntryPairs(
|
||||
outpointAndUTXOEntryPair.UTXOEntry.Amount,
|
||||
outpointAndUTXOEntryPair.UTXOEntry.ScriptPublicKey,
|
||||
outpointAndUTXOEntryPair.UTXOEntry.IsCoinbase,
|
||||
outpointAndUTXOEntryPair.UTXOEntry.BlockDAAScore,
|
||||
outpointAndUTXOEntryPair.UTXOEntry.BlockBlueScore,
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -288,7 +297,7 @@ func DomainOutpointAndUTXOEntryPairsToOutpointAndUTXOEntryPairs(
|
||||
Amount: outpointAndUTXOEntryPair.UTXOEntry.Amount(),
|
||||
ScriptPublicKey: outpointAndUTXOEntryPair.UTXOEntry.ScriptPublicKey(),
|
||||
IsCoinbase: outpointAndUTXOEntryPair.UTXOEntry.IsCoinbase(),
|
||||
BlockDAAScore: outpointAndUTXOEntryPair.UTXOEntry.BlockDAAScore(),
|
||||
BlockBlueScore: outpointAndUTXOEntryPair.UTXOEntry.BlockBlueScore(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,19 @@ import (
|
||||
// backing array multiple times.
|
||||
const defaultTransactionAlloc = 2048
|
||||
|
||||
// MaxMassAcceptedByBlock is the maximum total transaction mass a block may accept.
|
||||
const MaxMassAcceptedByBlock = 10000000
|
||||
|
||||
// MaxMassPerTx is the maximum total mass a transaction may have.
|
||||
const MaxMassPerTx = MaxMassAcceptedByBlock / 2
|
||||
|
||||
// MaxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const MaxTxPerBlock = (MaxMassAcceptedByBlock / minTxPayload) + 1
|
||||
|
||||
// MaxBlockParents is the maximum allowed number of parents for block.
|
||||
const MaxBlockParents = 10
|
||||
|
||||
// TxLoc holds locator data for the offset and length of where a transaction is
|
||||
// located within a MsgBlock data buffer.
|
||||
type TxLoc struct {
|
||||
|
||||
@@ -31,6 +31,6 @@ type OutpointAndUTXOEntryPair struct {
|
||||
type UTXOEntry struct {
|
||||
Amount uint64
|
||||
ScriptPublicKey *externalapi.ScriptPublicKey
|
||||
BlockDAAScore uint64
|
||||
BlockBlueScore uint64
|
||||
IsCoinbase bool
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package appmessage
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||
"strconv"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
@@ -132,6 +133,7 @@ type MsgTx struct {
|
||||
LockTime uint64
|
||||
SubnetworkID externalapi.DomainSubnetworkID
|
||||
Gas uint64
|
||||
PayloadHash externalapi.DomainHash
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
@@ -177,6 +179,7 @@ func (msg *MsgTx) Copy() *MsgTx {
|
||||
LockTime: msg.LockTime,
|
||||
SubnetworkID: msg.SubnetworkID,
|
||||
Gas: msg.Gas,
|
||||
PayloadHash: msg.PayloadHash,
|
||||
}
|
||||
|
||||
if msg.Payload != nil {
|
||||
@@ -277,12 +280,18 @@ func newMsgTx(version uint16, txIn []*TxIn, txOut []*TxOut, subnetworkID *extern
|
||||
txOut = make([]*TxOut, 0, defaultTxInOutAlloc)
|
||||
}
|
||||
|
||||
var payloadHash externalapi.DomainHash
|
||||
if *subnetworkID != subnetworks.SubnetworkIDNative {
|
||||
payloadHash = *hashes.PayloadHash(payload)
|
||||
}
|
||||
|
||||
return &MsgTx{
|
||||
Version: version,
|
||||
TxIn: txIn,
|
||||
TxOut: txOut,
|
||||
SubnetworkID: *subnetworkID,
|
||||
Gas: gas,
|
||||
PayloadHash: payloadHash,
|
||||
Payload: payload,
|
||||
LockTime: lockTime,
|
||||
}
|
||||
|
||||
@@ -133,8 +133,8 @@ func TestTx(t *testing.T) {
|
||||
|
||||
// TestTxHash tests the ability to generate the hash of a transaction accurately.
|
||||
func TestTxHashAndID(t *testing.T) {
|
||||
txHash1Str := "93663e597f6c968d32d229002f76408edf30d6a0151ff679fc729812d8cb2acc"
|
||||
txID1Str := "24079c6d2bdf602fc389cc307349054937744a9c8dc0f07c023e6af0e949a4e7"
|
||||
txHash1Str := "4bee9ee495bd93a755de428376bd582a2bb6ec37c041753b711c0606d5745c13"
|
||||
txID1Str := "f868bd20e816256b80eac976821be4589d24d21141bd1cec6e8005d0c16c6881"
|
||||
wantTxID1, err := transactionid.FromString(txID1Str)
|
||||
if err != nil {
|
||||
t.Fatalf("NewTxIDFromStr: %v", err)
|
||||
@@ -185,14 +185,14 @@ func TestTxHashAndID(t *testing.T) {
|
||||
spew.Sprint(tx1ID), spew.Sprint(wantTxID1))
|
||||
}
|
||||
|
||||
hash2Str := "8dafd1bec24527d8e3b443ceb0a3b92fffc0d60026317f890b2faf5e9afc177a"
|
||||
hash2Str := "cb1bdb4a83d4885535fb3cceb5c96597b7df903db83f0ffcd779d703affd8efd"
|
||||
wantHash2, err := externalapi.NewDomainHashFromString(hash2Str)
|
||||
if err != nil {
|
||||
t.Errorf("NewTxIDFromStr: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
id2Str := "89ffb49474637502d9059af38b8a95fc2f0d3baef5c801d7a9b9c8830671b711"
|
||||
id2Str := "ca080073d4ddf5b84443a0964af633f3c70a5b290fd3bc35a7e6f93fd33f9330"
|
||||
wantID2, err := transactionid.FromString(id2Str)
|
||||
if err != nil {
|
||||
t.Errorf("NewTxIDFromStr: %v", err)
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestVersion(t *testing.T) {
|
||||
|
||||
// Create version message data.
|
||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 16111}
|
||||
me := NewNetAddress(tcpAddrMe)
|
||||
me := NewNetAddress(tcpAddrMe, SFNodeNetwork)
|
||||
generatedID, err := id.GenerateID()
|
||||
if err != nil {
|
||||
t.Fatalf("id.GenerateID: %s", err)
|
||||
|
||||
@@ -15,6 +15,9 @@ type NetAddress struct {
|
||||
// Last time the address was seen.
|
||||
Timestamp mstime.Time
|
||||
|
||||
// Bitfield which identifies the services supported by the address.
|
||||
Services ServiceFlag
|
||||
|
||||
// IP address of the peer.
|
||||
IP net.IP
|
||||
|
||||
@@ -23,6 +26,17 @@ type NetAddress struct {
|
||||
Port uint16
|
||||
}
|
||||
|
||||
// HasService returns whether the specified service is supported by the address.
|
||||
func (na *NetAddress) HasService(service ServiceFlag) bool {
|
||||
return na.Services&service == service
|
||||
}
|
||||
|
||||
// AddService adds service as a supported service by the peer generating the
|
||||
// message.
|
||||
func (na *NetAddress) AddService(service ServiceFlag) {
|
||||
na.Services |= service
|
||||
}
|
||||
|
||||
// TCPAddress converts the NetAddress to *net.TCPAddr
|
||||
func (na *NetAddress) TCPAddress() *net.TCPAddr {
|
||||
return &net.TCPAddr{
|
||||
@@ -33,19 +47,20 @@ func (na *NetAddress) TCPAddress() *net.TCPAddr {
|
||||
|
||||
// NewNetAddressIPPort returns a new NetAddress using the provided IP, port, and
|
||||
// supported services with defaults for the remaining fields.
|
||||
func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress {
|
||||
return NewNetAddressTimestamp(mstime.Now(), ip, port)
|
||||
func NewNetAddressIPPort(ip net.IP, port uint16, services ServiceFlag) *NetAddress {
|
||||
return NewNetAddressTimestamp(mstime.Now(), services, ip, port)
|
||||
}
|
||||
|
||||
// NewNetAddressTimestamp returns a new NetAddress using the provided
|
||||
// timestamp, IP, port, and supported services. The timestamp is rounded to
|
||||
// single millisecond precision.
|
||||
func NewNetAddressTimestamp(
|
||||
timestamp mstime.Time, ip net.IP, port uint16) *NetAddress {
|
||||
timestamp mstime.Time, services ServiceFlag, ip net.IP, port uint16) *NetAddress {
|
||||
// Limit the timestamp to one millisecond precision since the protocol
|
||||
// doesn't support better.
|
||||
na := NetAddress{
|
||||
Timestamp: timestamp,
|
||||
Services: services,
|
||||
IP: ip,
|
||||
Port: port,
|
||||
}
|
||||
@@ -54,6 +69,6 @@ func NewNetAddressTimestamp(
|
||||
|
||||
// NewNetAddress returns a new NetAddress using the provided TCP address and
|
||||
// supported services with defaults for the remaining fields.
|
||||
func NewNetAddress(addr *net.TCPAddr) *NetAddress {
|
||||
return NewNetAddressIPPort(addr.IP, uint16(addr.Port))
|
||||
func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress {
|
||||
return NewNetAddressIPPort(addr.IP, uint16(addr.Port), services)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestNetAddress(t *testing.T) {
|
||||
port := 16111
|
||||
|
||||
// Test NewNetAddress.
|
||||
na := NewNetAddress(&net.TCPAddr{IP: ip, Port: port})
|
||||
na := NewNetAddress(&net.TCPAddr{IP: ip, Port: port}, 0)
|
||||
|
||||
// Ensure we get the same ip, port, and services back out.
|
||||
if !na.IP.Equal(ip) {
|
||||
@@ -25,4 +25,21 @@ func TestNetAddress(t *testing.T) {
|
||||
t.Errorf("NetNetAddress: wrong port - got %v, want %v", na.Port,
|
||||
port)
|
||||
}
|
||||
if na.Services != 0 {
|
||||
t.Errorf("NetNetAddress: wrong services - got %v, want %v",
|
||||
na.Services, 0)
|
||||
}
|
||||
if na.HasService(SFNodeNetwork) {
|
||||
t.Errorf("HasService: SFNodeNetwork service is set")
|
||||
}
|
||||
|
||||
// Ensure adding the full service node flag works.
|
||||
na.AddService(SFNodeNetwork)
|
||||
if na.Services != SFNodeNetwork {
|
||||
t.Errorf("AddService: wrong services - got %v, want %v",
|
||||
na.Services, SFNodeNetwork)
|
||||
}
|
||||
if !na.HasService(SFNodeNetwork) {
|
||||
t.Errorf("HasService: SFNodeNetwork service not set")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ type TransactionVerboseData struct {
|
||||
LockTime uint64
|
||||
SubnetworkID string
|
||||
Gas uint64
|
||||
PayloadHash string
|
||||
Payload string
|
||||
TransactionVerboseInputs []*TransactionVerboseInput
|
||||
TransactionVerboseOutputs []*TransactionVerboseOutput
|
||||
|
||||
@@ -20,8 +20,7 @@ func NewGeInfoRequestMessage() *GetInfoRequestMessage {
|
||||
// its respective RPC message
|
||||
type GetInfoResponseMessage struct {
|
||||
baseMessage
|
||||
P2PID string
|
||||
MempoolSize uint64
|
||||
P2PID string
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
@@ -32,9 +31,8 @@ func (msg *GetInfoResponseMessage) Command() MessageCommand {
|
||||
}
|
||||
|
||||
// NewGetInfoResponseMessage returns a instance of the message
|
||||
func NewGetInfoResponseMessage(p2pID string, mempoolSize uint64) *GetInfoResponseMessage {
|
||||
func NewGetInfoResponseMessage(p2pID string) *GetInfoResponseMessage {
|
||||
return &GetInfoResponseMessage{
|
||||
P2PID: p2pID,
|
||||
MempoolSize: mempoolSize,
|
||||
P2PID: p2pID,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ type RPCTransaction struct {
|
||||
LockTime uint64
|
||||
SubnetworkID string
|
||||
Gas uint64
|
||||
PayloadHash string
|
||||
Payload string
|
||||
}
|
||||
|
||||
@@ -85,6 +86,6 @@ type RPCOutpoint struct {
|
||||
type RPCUTXOEntry struct {
|
||||
Amount uint64
|
||||
ScriptPublicKey *RPCScriptPublicKey
|
||||
BlockDAAScore uint64
|
||||
BlockBlueScore uint64
|
||||
IsCoinbase bool
|
||||
}
|
||||
|
||||
@@ -72,8 +72,6 @@ func (a *ComponentManager) Stop() {
|
||||
log.Errorf("Error stopping the net adapter: %+v", err)
|
||||
}
|
||||
|
||||
a.protocolManager.Close()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -157,7 +155,7 @@ func setupRPC(
|
||||
|
||||
func (a *ComponentManager) maybeSeedFromDNS() {
|
||||
if !a.cfg.DisableDNSSeed {
|
||||
dnsseed.SeedFromDNS(a.cfg.NetParams(), a.cfg.DNSSeed, false, nil,
|
||||
dnsseed.SeedFromDNS(a.cfg.NetParams(), a.cfg.DNSSeed, appmessage.SFNodeNetwork, false, nil,
|
||||
a.cfg.Lookup, func(addresses []*appmessage.NetAddress) {
|
||||
// Kaspad uses a lookup of the dns seeder here. Since seeder returns
|
||||
// IPs of nodes and not its own IP, we can not know real IP of
|
||||
@@ -165,7 +163,7 @@ func (a *ComponentManager) maybeSeedFromDNS() {
|
||||
a.addressManager.AddAddresses(addresses...)
|
||||
})
|
||||
|
||||
dnsseed.SeedFromGRPC(a.cfg.NetParams(), a.cfg.GRPCSeed, false, nil,
|
||||
dnsseed.SeedFromGRPC(a.cfg.NetParams(), a.cfg.GRPCSeed, appmessage.SFNodeNetwork, false, nil,
|
||||
func(addresses []*appmessage.NetAddress) {
|
||||
a.addressManager.AddAddresses(addresses...)
|
||||
})
|
||||
|
||||
@@ -61,8 +61,6 @@ type FlowContext struct {
|
||||
|
||||
orphans map[externalapi.DomainHash]*externalapi.DomainBlock
|
||||
orphansMutex sync.RWMutex
|
||||
|
||||
shutdownChan chan struct{}
|
||||
}
|
||||
|
||||
// New returns a new instance of FlowContext.
|
||||
@@ -81,21 +79,9 @@ func New(cfg *config.Config, domain domain.Domain, addressManager *addressmanage
|
||||
transactionsToRebroadcast: make(map[externalapi.DomainTransactionID]*externalapi.DomainTransaction),
|
||||
orphans: make(map[externalapi.DomainHash]*externalapi.DomainBlock),
|
||||
timeStarted: mstime.Now().UnixMilliseconds(),
|
||||
shutdownChan: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Close signals to all flows the the protocol manager is closed.
|
||||
func (f *FlowContext) Close() {
|
||||
close(f.shutdownChan)
|
||||
}
|
||||
|
||||
// ShutdownChan is a chan where flows can subscribe to shutdown
|
||||
// event.
|
||||
func (f *FlowContext) ShutdownChan() <-chan struct{} {
|
||||
return f.shutdownChan
|
||||
}
|
||||
|
||||
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
||||
func (f *FlowContext) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler OnBlockAddedToDAGHandler) {
|
||||
f.onBlockAddedToDAGHandler = onBlockAddedToDAGHandler
|
||||
|
||||
@@ -50,7 +50,7 @@ func (flow *handleRequestHeadersFlow) start() error {
|
||||
// GetHashesBetween is a relatively heavy operation so we limit it
|
||||
// in order to avoid locking the consensus for too long
|
||||
const maxBlueScoreDifference = 1 << 10
|
||||
blockHashes, _, err := flow.Domain().Consensus().GetHashesBetween(lowHash, highHash, maxBlueScoreDifference)
|
||||
blockHashes, err := flow.Domain().Consensus().GetHashesBetween(lowHash, highHash, maxBlueScoreDifference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
|
||||
// SendPingsContext is the interface for the context needed for the SendPings flow.
|
||||
type SendPingsContext interface {
|
||||
ShutdownChan() <-chan struct{}
|
||||
}
|
||||
|
||||
type sendPingsFlow struct {
|
||||
@@ -40,13 +39,7 @@ func (flow *sendPingsFlow) start() error {
|
||||
ticker := time.NewTicker(pingInterval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-flow.ShutdownChan():
|
||||
return nil
|
||||
case <-ticker.C:
|
||||
}
|
||||
|
||||
for range ticker.C {
|
||||
nonce, err := random.Uint64()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -69,4 +62,5 @@ func (flow *sendPingsFlow) start() error {
|
||||
}
|
||||
flow.peer.SetPingIdle()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ func (f *fakeRelayInvsContext) GetBlockAcceptanceData(blockHash *externalapi.Dom
|
||||
panic(errors.Errorf("called unimplemented function from test '%s'", f.testName))
|
||||
}
|
||||
|
||||
func (f *fakeRelayInvsContext) GetHashesBetween(lowHash, highHash *externalapi.DomainHash, maxBlueScoreDifference uint64) (hashes []*externalapi.DomainHash, actualHighHash *externalapi.DomainHash, err error) {
|
||||
func (f *fakeRelayInvsContext) GetHashesBetween(lowHash, highHash *externalapi.DomainHash, maxBlueScoreDifference uint64) ([]*externalapi.DomainHash, error) {
|
||||
panic(errors.Errorf("called unimplemented function from test '%s'", f.testName))
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@ package protocol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain"
|
||||
|
||||
@@ -20,9 +17,7 @@ import (
|
||||
|
||||
// Manager manages the p2p protocol
|
||||
type Manager struct {
|
||||
context *flowcontext.FlowContext
|
||||
routersWaitGroup sync.WaitGroup
|
||||
isClosed uint32
|
||||
context *flowcontext.FlowContext
|
||||
}
|
||||
|
||||
// NewManager creates a new instance of the p2p protocol manager
|
||||
@@ -37,18 +32,6 @@ func NewManager(cfg *config.Config, domain domain.Domain, netAdapter *netadapter
|
||||
return &manager, nil
|
||||
}
|
||||
|
||||
// Close closes the protocol manager and waits until all p2p flows
|
||||
// finish.
|
||||
func (m *Manager) Close() {
|
||||
if !atomic.CompareAndSwapUint32(&m.isClosed, 0, 1) {
|
||||
panic(errors.New("The protocol manager was already closed"))
|
||||
}
|
||||
|
||||
atomic.StoreUint32(&m.isClosed, 1)
|
||||
m.context.Close()
|
||||
m.routersWaitGroup.Wait()
|
||||
}
|
||||
|
||||
// Peers returns the currently active peers
|
||||
func (m *Manager) Peers() []*peerpkg.Peer {
|
||||
return m.context.Peers()
|
||||
@@ -70,13 +53,11 @@ func (m *Manager) AddBlock(block *externalapi.DomainBlock) error {
|
||||
return m.context.AddBlock(block)
|
||||
}
|
||||
|
||||
func (m *Manager) runFlows(flows []*flow, peer *peerpkg.Peer, errChan <-chan error, flowsWaitGroup *sync.WaitGroup) error {
|
||||
flowsWaitGroup.Add(len(flows))
|
||||
func (m *Manager) runFlows(flows []*flow, peer *peerpkg.Peer, errChan <-chan error) error {
|
||||
for _, flow := range flows {
|
||||
executeFunc := flow.executeFunc // extract to new variable so that it's not overwritten
|
||||
spawn(fmt.Sprintf("flow-%s", flow.name), func() {
|
||||
executeFunc(peer)
|
||||
flowsWaitGroup.Done()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/protocol/flows/rejects"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/protocol/flows/addressexchange"
|
||||
@@ -41,13 +41,6 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net
|
||||
// After flows were registered - spawn a new thread that will wait for connection to finish initializing
|
||||
// and start receiving messages
|
||||
spawn("routerInitializer-runFlows", func() {
|
||||
m.routersWaitGroup.Add(1)
|
||||
defer m.routersWaitGroup.Done()
|
||||
|
||||
if atomic.LoadUint32(&m.isClosed) == 1 {
|
||||
panic(errors.Errorf("tried to initialize router when the protocol manager is closed"))
|
||||
}
|
||||
|
||||
isBanned, err := m.context.ConnectionManager().IsBanned(netConnection)
|
||||
if err != nil && !errors.Is(err, addressmanager.ErrAddressNotFound) {
|
||||
panic(err)
|
||||
@@ -86,17 +79,11 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net
|
||||
|
||||
removeHandshakeRoutes(router)
|
||||
|
||||
flowsWaitGroup := &sync.WaitGroup{}
|
||||
err = m.runFlows(flows, peer, errChan, flowsWaitGroup)
|
||||
err = m.runFlows(flows, peer, errChan)
|
||||
if err != nil {
|
||||
m.handleError(err, netConnection, router.OutgoingRoute())
|
||||
// We call `flowsWaitGroup.Wait()` in two places instead of deferring, because
|
||||
// we already defer `m.routersWaitGroup.Done()`, so we try to avoid error prone
|
||||
// and confusing use of multiple dependent defers.
|
||||
flowsWaitGroup.Wait()
|
||||
return
|
||||
}
|
||||
flowsWaitGroup.Wait()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -251,7 +238,7 @@ func (m *Manager) registerTransactionRelayFlow(router *routerpkg.Router, isStopp
|
||||
outgoingRoute := router.OutgoingRoute()
|
||||
|
||||
return []*flow{
|
||||
m.registerFlowWithCapacity("HandleRelayedTransactions", 10_000, router,
|
||||
m.registerFlow("HandleRelayedTransactions", router,
|
||||
[]appmessage.MessageCommand{appmessage.CmdInvTransaction, appmessage.CmdTx, appmessage.CmdTransactionNotFound}, isStopping, errChan,
|
||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||
return transactionrelay.HandleRelayedTransactions(m.context, incomingRoute, outgoingRoute)
|
||||
@@ -287,24 +274,6 @@ func (m *Manager) registerFlow(name string, router *routerpkg.Router, messageTyp
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return m.registerFlowForRoute(route, name, isStopping, errChan, initializeFunc)
|
||||
}
|
||||
|
||||
func (m *Manager) registerFlowWithCapacity(name string, capacity int, router *routerpkg.Router,
|
||||
messageTypes []appmessage.MessageCommand, isStopping *uint32,
|
||||
errChan chan error, initializeFunc flowInitializeFunc) *flow {
|
||||
|
||||
route, err := router.AddIncomingRouteWithCapacity(capacity, messageTypes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return m.registerFlowForRoute(route, name, isStopping, errChan, initializeFunc)
|
||||
}
|
||||
|
||||
func (m *Manager) registerFlowForRoute(route *routerpkg.Route, name string, isStopping *uint32,
|
||||
errChan chan error, initializeFunc flowInitializeFunc) *flow {
|
||||
|
||||
return &flow{
|
||||
name: name,
|
||||
executeFunc: func(peer *peerpkg.Peer) {
|
||||
|
||||
@@ -24,7 +24,7 @@ func ConvertUTXOOutpointEntryPairsToUTXOsByAddressesEntries(address string, pair
|
||||
UTXOEntry: &appmessage.RPCUTXOEntry{
|
||||
Amount: utxoEntry.Amount(),
|
||||
ScriptPublicKey: &appmessage.RPCScriptPublicKey{Script: hex.EncodeToString(utxoEntry.ScriptPublicKey().Script), Version: utxoEntry.ScriptPublicKey().Version},
|
||||
BlockDAAScore: utxoEntry.BlockDAAScore(),
|
||||
BlockBlueScore: utxoEntry.BlockBlueScore(),
|
||||
IsCoinbase: utxoEntry.IsCoinbase(),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
@@ -126,6 +128,11 @@ func (ctx *Context) BuildTransactionVerboseData(tx *externalapi.DomainTransactio
|
||||
onEnd := logger.LogAndMeasureExecutionTime(log, "BuildTransactionVerboseData")
|
||||
defer onEnd()
|
||||
|
||||
var payloadHash string
|
||||
if tx.SubnetworkID != subnetworks.SubnetworkIDNative {
|
||||
payloadHash = tx.PayloadHash.String()
|
||||
}
|
||||
|
||||
txReply := &appmessage.TransactionVerboseData{
|
||||
TxID: txID,
|
||||
Hash: consensushashing.TransactionHash(tx).String(),
|
||||
@@ -136,6 +143,7 @@ func (ctx *Context) BuildTransactionVerboseData(tx *externalapi.DomainTransactio
|
||||
LockTime: tx.LockTime,
|
||||
SubnetworkID: tx.SubnetworkID.String(),
|
||||
Gas: tx.Gas,
|
||||
PayloadHash: payloadHash,
|
||||
Payload: hex.EncodeToString(tx.Payload),
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func HandleGetBlocks(context *rpccontext.Context, _ *router.Router, request appm
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockHashes, highHash, err := context.Domain.Consensus().GetHashesBetween(
|
||||
blockHashes, err := context.Domain.Consensus().GetHashesBetween(
|
||||
lowHash, virtualSelectedParent, maxBlocksInGetBlocksResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -64,10 +64,9 @@ func HandleGetBlocks(context *rpccontext.Context, _ *router.Router, request appm
|
||||
// prepend low hash to make it inclusive
|
||||
blockHashes = append([]*externalapi.DomainHash{lowHash}, blockHashes...)
|
||||
|
||||
// If the high hash is equal to virtualSelectedParent it means GetHashesBetween didn't skip any hashes, and
|
||||
// there's space to add the virtualSelectedParent's anticone, otherwise you can't add the anticone because
|
||||
// there's no guarantee that all of the anticone root ancestors will be present.
|
||||
if highHash.Equal(virtualSelectedParent) {
|
||||
// If there are no maxBlocksInGetBlocksResponse between lowHash and virtualSelectedParent -
|
||||
// add virtualSelectedParent's anticone
|
||||
if len(blockHashes) < maxBlocksInGetBlocksResponse {
|
||||
virtualSelectedParentAnticone, err := context.Domain.Consensus().Anticone(virtualSelectedParent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -8,10 +8,6 @@ import (
|
||||
|
||||
// HandleGetInfo handles the respectively named RPC command
|
||||
func HandleGetInfo(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
||||
response := appmessage.NewGetInfoResponseMessage(
|
||||
context.NetAdapter.ID().String(),
|
||||
uint64(context.Domain.MiningManager().TransactionCount()),
|
||||
)
|
||||
|
||||
response := appmessage.NewGetInfoResponseMessage(context.NetAdapter.ID().String())
|
||||
return response, nil
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func HandleUnban(context *rpccontext.Context, _ *router.Router, request appmessa
|
||||
errorMessage.Error = appmessage.RPCErrorf("Could not parse IP %s", unbanRequest.IP)
|
||||
return errorMessage, nil
|
||||
}
|
||||
err := context.AddressManager.Unban(appmessage.NewNetAddressIPPort(ip, 0))
|
||||
err := context.AddressManager.Unban(appmessage.NewNetAddressIPPort(ip, 0, 0))
|
||||
if err != nil {
|
||||
errorMessage := &appmessage.UnbanResponseMessage{}
|
||||
errorMessage.Error = appmessage.RPCErrorf("Could not unban IP: %s", err)
|
||||
|
||||
@@ -1,11 +1,35 @@
|
||||
|
||||
Kaspad v0.9.1 - 2021-03-14
|
||||
===========================
|
||||
* Testnet network reset
|
||||
|
||||
Kaspad v0.9.0 - 2021-03-04
|
||||
===========================
|
||||
|
||||
* Merge big subdags in pick virtual parents (#1574)
|
||||
* Write in the reject message the tx rejection reason (#1573)
|
||||
* Add nil checks for protowire (#1570)
|
||||
* Increase getBlocks limit to 1000 (#1572)
|
||||
* Return RPC error if getBlock's lowHash doesn't exist (#1569)
|
||||
* Add default dns-seeder to testnet (#1568)
|
||||
* Fix utxoindex deserialization (#1566)
|
||||
* Add pruning point hash to GetBlockDagInfo response (#1565)
|
||||
* Use EmitUnpopulated so that kaspactl prints all fields, even the default ones (#1561)
|
||||
* Stop logging an error whenever an RPC/P2P connection is canceled (#1562)
|
||||
* Cleanup the logger and make it asynchronous (#1524)
|
||||
* Close all iterators (#1542)
|
||||
* Add childrenHashes to GetBlock/s RPC commands (#1560)
|
||||
* Add ScriptPublicKey.Version to RPC (#1559)
|
||||
* Fix the target block rate to create less bursty mining (#1554)
|
||||
|
||||
Kaspad v0.8.10 - 2021-02-25
|
||||
===========================
|
||||
|
||||
[*] Fix bug where invalid mempool transactions were not removed (#1551)
|
||||
[*] Add RPC reconnection to the miner (#1552)
|
||||
[*] Remove virtual diff parents - only selectedTip is virtualDiffParent now (#1550)
|
||||
[*] Fix UTXO index (#1548)
|
||||
[*] Prevent fast failing (#1545)
|
||||
[*] Increase the sleep time in kaspaminer when the node is not synced (#1544)
|
||||
[*] Disallow header only blocks on RPC, relay and when requesting IBD full blocks (#1537)
|
||||
[*] Make templateManager hold a DomainBlock and isSynced bool instead of a GetBlockTemplateResponseMessage (#1538)
|
||||
* Fix bug where invalid mempool transactions were not removed (#1551)
|
||||
* Add RPC reconnection to the miner (#1552)
|
||||
* Remove virtual diff parents - only selectedTip is virtualDiffParent now (#1550)
|
||||
* Fix UTXO index (#1548)
|
||||
* Prevent fast failing (#1545)
|
||||
* Increase the sleep time in kaspaminer when the node is not synced (#1544)
|
||||
* Disallow header only blocks on RPC, relay and when requesting IBD full blocks (#1537)
|
||||
* Make templateManager hold a DomainBlock and isSynced bool instead of a GetBlockTemplateResponseMessage (#1538)
|
||||
|
||||
@@ -24,9 +24,9 @@ const (
|
||||
|
||||
var (
|
||||
// Default configuration options
|
||||
defaultAppDir = util.AppDir("kaspaminer", false)
|
||||
defaultLogFile = filepath.Join(defaultAppDir, defaultLogFilename)
|
||||
defaultErrLogFile = filepath.Join(defaultAppDir, defaultErrLogFilename)
|
||||
defaultHomeDir = util.AppDataDir("kaspaminer", false)
|
||||
defaultLogFile = filepath.Join(defaultHomeDir, defaultLogFilename)
|
||||
defaultErrLogFile = filepath.Join(defaultHomeDir, defaultErrLogFilename)
|
||||
defaultRPCServer = "localhost"
|
||||
)
|
||||
|
||||
|
||||
@@ -44,32 +44,34 @@ func mineLoop(client *minerClient, numberOfBlocks uint64, targetBlocksPerSecond
|
||||
|
||||
spawn("blocksLoop", func() {
|
||||
const windowSize = 10
|
||||
var expectedDurationForWindow time.Duration
|
||||
var windowExpectedEndTime time.Time
|
||||
hasBlockRateTarget := targetBlocksPerSecond != 0
|
||||
var windowTicker, blockTicker *time.Ticker
|
||||
// We use tickers to limit the block rate:
|
||||
// 1. windowTicker -> makes sure that the last windowSize blocks take at least windowSize*targetBlocksPerSecond.
|
||||
// 2. blockTicker -> makes sure that each block takes at least targetBlocksPerSecond/windowSize.
|
||||
// that way we both allow for fluctuation in block rate but also make sure they're not too big (by an order of magnitude)
|
||||
if hasBlockRateTarget {
|
||||
windowRate := time.Duration(float64(time.Second) / (targetBlocksPerSecond / windowSize))
|
||||
blockRate := time.Duration(float64(time.Second) / (targetBlocksPerSecond * windowSize))
|
||||
log.Infof("Minimum average time per %d blocks: %s, smaller minimum time per block: %s", windowSize, windowRate, blockRate)
|
||||
windowTicker = time.NewTicker(windowRate)
|
||||
blockTicker = time.NewTicker(blockRate)
|
||||
defer windowTicker.Stop()
|
||||
defer blockTicker.Stop()
|
||||
expectedDurationForWindow = time.Duration(float64(windowSize)/targetBlocksPerSecond) * time.Second
|
||||
windowExpectedEndTime = time.Now().Add(expectedDurationForWindow)
|
||||
}
|
||||
windowStart := time.Now()
|
||||
for blockIndex := 1; ; blockIndex++ {
|
||||
blockInWindowIndex := 0
|
||||
|
||||
sleepTime := 0 * time.Second
|
||||
|
||||
for {
|
||||
foundBlockChan <- mineNextBlock(mineWhenNotSynced)
|
||||
|
||||
if hasBlockRateTarget {
|
||||
<-blockTicker.C
|
||||
if (blockIndex % windowSize) == 0 {
|
||||
tickerStart := time.Now()
|
||||
<-windowTicker.C
|
||||
log.Infof("Finished mining %d blocks in: %s. slept for: %s", windowSize, time.Since(windowStart), time.Since(tickerStart))
|
||||
windowStart = time.Now()
|
||||
blockInWindowIndex++
|
||||
if blockInWindowIndex == windowSize-1 {
|
||||
deviation := windowExpectedEndTime.Sub(time.Now())
|
||||
if deviation > 0 {
|
||||
sleepTime = deviation / windowSize
|
||||
log.Infof("Finished to mine %d blocks %s earlier than expected. Setting the miner "+
|
||||
"to sleep %s between blocks to compensate",
|
||||
windowSize, deviation, sleepTime)
|
||||
}
|
||||
blockInWindowIndex = 0
|
||||
windowExpectedEndTime = time.Now().Add(expectedDurationForWindow)
|
||||
}
|
||||
time.Sleep(sleepTime)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,8 +10,7 @@ func isUTXOSpendable(entry *appmessage.UTXOsByAddressesEntry, virtualSelectedPar
|
||||
if !entry.UTXOEntry.IsCoinbase {
|
||||
return true
|
||||
}
|
||||
blockBlueScore := entry.UTXOEntry.BlockDAAScore
|
||||
// TODO: Check for a better alternative than virtualSelectedParentBlueScore
|
||||
blockBlueScore := entry.UTXOEntry.BlockBlueScore
|
||||
return blockBlueScore+coinbaseMaturity < virtualSelectedParentBlueScore
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,9 @@ package main
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionid"
|
||||
@@ -179,12 +177,11 @@ func generateTransaction(keyPair *secp256k1.SchnorrKeyPair, selectedUTXOs []*app
|
||||
SubnetworkID: subnetworks.SubnetworkIDNative,
|
||||
Gas: 0,
|
||||
Payload: nil,
|
||||
PayloadHash: externalapi.DomainHash{},
|
||||
}
|
||||
sighashReusedValues := &consensushashing.SighashReusedValues{}
|
||||
|
||||
for i, input := range domainTransaction.Inputs {
|
||||
signatureScript, err := txscript.SignatureScript(
|
||||
domainTransaction, i, consensushashing.SigHashAll, keyPair, sighashReusedValues)
|
||||
signatureScript, err := txscript.SignatureScript(domainTransaction, i, fromScript, txscript.SigHashAll, keyPair)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ type consensus struct {
|
||||
utxoDiffStore model.UTXODiffStore
|
||||
finalityStore model.FinalityStore
|
||||
headersSelectedChainStore model.HeadersSelectedChainStore
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
}
|
||||
|
||||
// BuildBlock builds a block over the current state, with the transactions
|
||||
@@ -159,8 +158,6 @@ func (s *consensus) GetBlockInfo(blockHash *externalapi.DomainHash) (*externalap
|
||||
}
|
||||
|
||||
func (s *consensus) GetBlockChildren(blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
blockRelation, err := s.blockRelationStore.BlockRelation(s.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -182,18 +179,18 @@ func (s *consensus) GetBlockAcceptanceData(blockHash *externalapi.DomainHash) (e
|
||||
}
|
||||
|
||||
func (s *consensus) GetHashesBetween(lowHash, highHash *externalapi.DomainHash,
|
||||
maxBlueScoreDifference uint64) (hashes []*externalapi.DomainHash, actualHighHash *externalapi.DomainHash, err error) {
|
||||
maxBlueScoreDifference uint64) ([]*externalapi.DomainHash, error) {
|
||||
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
err = s.validateBlockHashExists(lowHash)
|
||||
err := s.validateBlockHashExists(lowHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
err = s.validateBlockHashExists(highHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.syncManager.GetHashesBetween(lowHash, highHash, maxBlueScoreDifference)
|
||||
|
||||
@@ -13,9 +13,9 @@ type GHOSTDAGManagerConstructor func(model.DBReader, model.DAGTopologyManager,
|
||||
|
||||
// DifficultyManagerConstructor is the function signature for a constructor of a type implementing model.DifficultyManager
|
||||
type DifficultyManagerConstructor func(model.DBReader, model.GHOSTDAGManager, model.GHOSTDAGDataStore,
|
||||
model.BlockHeaderStore, model.DAABlocksStore, model.DAGTopologyManager, model.DAGTraversalManager, *big.Int, int, bool, time.Duration,
|
||||
model.BlockHeaderStore, model.DAGTopologyManager, model.DAGTraversalManager, *big.Int, int, bool, time.Duration,
|
||||
*externalapi.DomainHash) model.DifficultyManager
|
||||
|
||||
// PastMedianTimeManagerConstructor is the function signature for a constructor of a type implementing model.PastMedianTimeManager
|
||||
type PastMedianTimeManagerConstructor func(int, model.DBReader, model.DAGTraversalManager, model.BlockHeaderStore,
|
||||
model.GHOSTDAGDataStore, *externalapi.DomainHash) model.PastMedianTimeManager
|
||||
model.GHOSTDAGDataStore) model.PastMedianTimeManager
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package binaryserialization
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const uint64Length = 8
|
||||
|
||||
// SerializeUint64 serializes a uint64
|
||||
func SerializeUint64(value uint64) []byte {
|
||||
var keyBytes [uint64Length]byte
|
||||
binary.LittleEndian.PutUint64(keyBytes[:], value)
|
||||
return keyBytes[:]
|
||||
}
|
||||
|
||||
// DeserializeUint64 deserializes bytes to uint64
|
||||
func DeserializeUint64(valueBytes []byte) (uint64, error) {
|
||||
if len(valueBytes) != uint64Length {
|
||||
return 0, errors.Errorf("the given value is %d bytes so it cannot be deserialized into uint64",
|
||||
len(valueBytes))
|
||||
}
|
||||
return binary.LittleEndian.Uint64(valueBytes), nil
|
||||
}
|
||||
@@ -1,47 +1,13 @@
|
||||
package binaryserialization
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
// SerializeHash serializes hash to a slice of bytes
|
||||
func SerializeHash(hash *externalapi.DomainHash) []byte {
|
||||
return hash.ByteSlice()
|
||||
}
|
||||
|
||||
// DeserializeHash deserializes a slice of bytes to a hash
|
||||
// DeserializeHash a slice of bytes to a hash
|
||||
func DeserializeHash(hashBytes []byte) (*externalapi.DomainHash, error) {
|
||||
return externalapi.NewDomainHashFromByteSlice(hashBytes)
|
||||
}
|
||||
|
||||
// SerializeHashes serializes a slice of hashes to a slice of bytes
|
||||
func SerializeHashes(hashes []*externalapi.DomainHash) []byte {
|
||||
buff := make([]byte, len(hashes)*externalapi.DomainHashSize)
|
||||
for i, hash := range hashes {
|
||||
copy(buff[externalapi.DomainHashSize*i:], hash.ByteSlice())
|
||||
}
|
||||
|
||||
return buff
|
||||
}
|
||||
|
||||
// DeserializeHashes deserializes a slice of bytes to a slice of hashes
|
||||
func DeserializeHashes(hashesBytes []byte) ([]*externalapi.DomainHash, error) {
|
||||
if len(hashesBytes)%externalapi.DomainHashSize != 0 {
|
||||
return nil, errors.Errorf("The length of hashBytes is not divisible by externalapi.DomainHashSize (%d)",
|
||||
externalapi.DomainHashSize)
|
||||
}
|
||||
|
||||
numHashes := len(hashesBytes) / externalapi.DomainHashSize
|
||||
hashes := make([]*externalapi.DomainHash, numHashes)
|
||||
for i := 0; i < numHashes; i++ {
|
||||
var err error
|
||||
start := i * externalapi.DomainHashSize
|
||||
end := i*externalapi.DomainHashSize + externalapi.DomainHashSize
|
||||
hashes[i], err = externalapi.NewDomainHashFromByteSlice(hashesBytes[start:end])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return hashes, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package binaryserialization
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// SerializeChainBlockIndex serializes chain block index
|
||||
func SerializeChainBlockIndex(index uint64) []byte {
|
||||
var keyBytes [8]byte
|
||||
binary.LittleEndian.PutUint64(keyBytes[:], index)
|
||||
return keyBytes[:]
|
||||
}
|
||||
|
||||
// DeserializeChainBlockIndex deserializes chain block index to uint64
|
||||
func DeserializeChainBlockIndex(indexBytes []byte) uint64 {
|
||||
return binary.LittleEndian.Uint64(indexBytes)
|
||||
}
|
||||
@@ -241,6 +241,7 @@ type DbTransaction struct {
|
||||
LockTime uint64 `protobuf:"varint,4,opt,name=lockTime,proto3" json:"lockTime,omitempty"`
|
||||
SubnetworkID *DbSubnetworkId `protobuf:"bytes,5,opt,name=subnetworkID,proto3" json:"subnetworkID,omitempty"`
|
||||
Gas uint64 `protobuf:"varint,6,opt,name=gas,proto3" json:"gas,omitempty"`
|
||||
PayloadHash *DbHash `protobuf:"bytes,7,opt,name=payloadHash,proto3" json:"payloadHash,omitempty"`
|
||||
Payload []byte `protobuf:"bytes,8,opt,name=payload,proto3" json:"payload,omitempty"`
|
||||
}
|
||||
|
||||
@@ -318,6 +319,13 @@ func (x *DbTransaction) GetGas() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DbTransaction) GetPayloadHash() *DbHash {
|
||||
if x != nil {
|
||||
return x.PayloadHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *DbTransaction) GetPayload() []byte {
|
||||
if x != nil {
|
||||
return x.Payload
|
||||
@@ -1220,7 +1228,7 @@ type DbUtxoEntry struct {
|
||||
|
||||
Amount uint64 `protobuf:"varint,1,opt,name=amount,proto3" json:"amount,omitempty"`
|
||||
ScriptPublicKey *DbScriptPublicKey `protobuf:"bytes,2,opt,name=scriptPublicKey,proto3" json:"scriptPublicKey,omitempty"`
|
||||
BlockDaaScore uint64 `protobuf:"varint,3,opt,name=blockDaaScore,proto3" json:"blockDaaScore,omitempty"`
|
||||
BlockBlueScore uint64 `protobuf:"varint,3,opt,name=blockBlueScore,proto3" json:"blockBlueScore,omitempty"`
|
||||
IsCoinbase bool `protobuf:"varint,4,opt,name=isCoinbase,proto3" json:"isCoinbase,omitempty"`
|
||||
}
|
||||
|
||||
@@ -1270,9 +1278,9 @@ func (x *DbUtxoEntry) GetScriptPublicKey() *DbScriptPublicKey {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *DbUtxoEntry) GetBlockDaaScore() uint64 {
|
||||
func (x *DbUtxoEntry) GetBlockBlueScore() uint64 {
|
||||
if x != nil {
|
||||
return x.BlockDaaScore
|
||||
return x.BlockBlueScore
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -1645,7 +1653,7 @@ var file_dbobjects_proto_rawDesc = []byte{
|
||||
0x28, 0x0d, 0x52, 0x04, 0x62, 0x69, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63,
|
||||
0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x1c,
|
||||
0x0a, 0x06, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0xad, 0x02, 0x0a,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0xe6, 0x02, 0x0a,
|
||||
0x0d, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75,
|
||||
@@ -1663,184 +1671,188 @@ var file_dbobjects_proto_rawDesc = []byte{
|
||||
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
|
||||
0x49, 0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x44,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67,
|
||||
0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xa1, 0x01, 0x0a,
|
||||
0x12, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e,
|
||||
0x70, 0x75, 0x74, 0x12, 0x45, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f,
|
||||
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62,
|
||||
0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f,
|
||||
0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65,
|
||||
0x22, 0x68, 0x0a, 0x0a, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x44,
|
||||
0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
|
||||
0x61, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x61, 0x73,
|
||||
0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0b,
|
||||
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x70,
|
||||
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61,
|
||||
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x12, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x45, 0x0a, 0x10,
|
||||
0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
|
||||
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e,
|
||||
0x74, 0x52, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a,
|
||||
0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||
0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x68, 0x0a, 0x0a, 0x44, 0x62, 0x4f,
|
||||
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
|
||||
0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0d,
|
||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x22, 0x37, 0x0a, 0x0f, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x74,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x13,
|
||||
0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74,
|
||||
0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x34, 0x0a, 0x0e, 0x44, 0x62, 0x53, 0x75, 0x62, 0x6e, 0x65,
|
||||
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65,
|
||||
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73,
|
||||
0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x22, 0x6a, 0x0a, 0x10, 0x44,
|
||||
0x62, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12,
|
||||
0x56, 0x0a, 0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61,
|
||||
0x74, 0x61, 0x52, 0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0xb6, 0x01, 0x0a, 0x15, 0x44, 0x62, 0x42, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74,
|
||||
0x61, 0x12, 0x68, 0x0a, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61,
|
||||
0x52, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63,
|
||||
0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x09, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
|
||||
0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68,
|
||||
0x22, 0xed, 0x01, 0x0a, 0x1b, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61,
|
||||
0x12, 0x3e, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x37, 0x0a, 0x0f, 0x44, 0x62,
|
||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a,
|
||||
0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x13, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
||||
0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
||||
0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x34, 0x0a, 0x0e,
|
||||
0x44, 0x62, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x22,
|
||||
0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
|
||||
0x49, 0x64, 0x22, 0x6a, 0x0a, 0x10, 0x44, 0x62, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x56, 0x0a, 0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41,
|
||||
0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70,
|
||||
0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0xb6,
|
||||
0x01, 0x0a, 0x15, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x68, 0x0a, 0x19, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61,
|
||||
0x74, 0x61, 0x12, 0x33, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x09, 0x62, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0xed, 0x01, 0x0a, 0x1b, 0x44, 0x62, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x41,
|
||||
0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69,
|
||||
0x73, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x5c, 0x0a, 0x1b, 0x74, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x55, 0x74, 0x78,
|
||||
0x6f, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
|
||||
0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1b, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x55, 0x74, 0x78, 0x6f,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x76, 0x0a, 0x10, 0x44, 0x62, 0x42, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x70,
|
||||
0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48,
|
||||
0x61, 0x73, 0x68, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x08,
|
||||
0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
|
||||
0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22,
|
||||
0x27, 0x0a, 0x0d, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xdb, 0x02, 0x0a, 0x13, 0x44, 0x62, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a,
|
||||
0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x12, 0x3d, 0x0a, 0x0e, 0x73, 0x65,
|
||||
0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63,
|
||||
0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x0d, 0x6d, 0x65, 0x72,
|
||||
0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65,
|
||||
0x74, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53,
|
||||
0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48,
|
||||
0x61, 0x73, 0x68, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64,
|
||||
0x73, 0x12, 0x53, 0x0a, 0x12, 0x62, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f,
|
||||
0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62,
|
||||
0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x73, 0x52, 0x12, 0x62, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e,
|
||||
0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x22, 0x6d, 0x0a, 0x14, 0x44, 0x62, 0x42, 0x6c, 0x75, 0x65,
|
||||
0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x12, 0x31,
|
||||
0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48, 0x61, 0x73,
|
||||
0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e,
|
||||
0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x28, 0x0a, 0x0a, 0x44, 0x62, 0x4d, 0x75, 0x6c, 0x74, 0x69,
|
||||
0x73, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x22,
|
||||
0x46, 0x0a, 0x09, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x53, 0x65, 0x74, 0x12, 0x39, 0x0a, 0x05,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74,
|
||||
0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d,
|
||||
0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x87, 0x01, 0x0a, 0x14, 0x44, 0x62, 0x55, 0x74,
|
||||
0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d,
|
||||
0x12, 0x35, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f,
|
||||
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45,
|
||||
0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72,
|
||||
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78,
|
||||
0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xb7, 0x01, 0x0a, 0x0b, 0x44, 0x62, 0x55,
|
||||
0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
||||
0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
||||
0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x0d,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61,
|
||||
0x73, 0x65, 0x22, 0xfe, 0x01, 0x0a, 0x12, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62,
|
||||
0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x08, 0x63, 0x68, 0x69,
|
||||
0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66,
|
||||
0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74,
|
||||
0x65, 0x64, 0x12, 0x5c, 0x0a, 0x1b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65,
|
||||
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e,
|
||||
0x74, 0x72, 0x79, 0x52, 0x1b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x49, 0x6e, 0x70, 0x75, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73,
|
||||
0x22, 0x76, 0x0a, 0x10, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18,
|
||||
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x70, 0x61,
|
||||
0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65,
|
||||
0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08,
|
||||
0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x27, 0x0a, 0x0d, 0x44, 0x62, 0x42, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61,
|
||||
0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x22, 0xdb, 0x02, 0x0a, 0x13, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f,
|
||||
0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75,
|
||||
0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c,
|
||||
0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57,
|
||||
0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57,
|
||||
0x6f, 0x72, 0x6b, 0x12, 0x3d, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50,
|
||||
0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61,
|
||||
0x73, 0x68, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x2d, 0x0a, 0x06,
|
||||
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48,
|
||||
0x61, 0x73, 0x68, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x08, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62,
|
||||
0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x76, 0x61, 0x6c, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x43,
|
||||
0x0a, 0x11, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x53, 0x65, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
||||
0x73, 0x68, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65,
|
||||
0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c,
|
||||
0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
||||
0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68,
|
||||
0x52, 0x11, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x53, 0x65, 0x74, 0x22, 0x40, 0x0a, 0x16, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62,
|
||||
0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x74,
|
||||
0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x88, 0x01, 0x0a, 0x0a, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f,
|
||||
0x44, 0x69, 0x66, 0x66, 0x12, 0x39, 0x0a, 0x05, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x12,
|
||||
0x3f, 0x0a, 0x08, 0x74, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x74, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x22, 0x33, 0x0a, 0x06, 0x44, 0x62, 0x54, 0x69, 0x70, 0x73, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x69,
|
||||
0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
|
||||
0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52,
|
||||
0x04, 0x74, 0x69, 0x70, 0x73, 0x22, 0x24, 0x0a, 0x0c, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x2a, 0x0a, 0x12, 0x44,
|
||||
0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b,
|
||||
0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x52, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x12,
|
||||
0x39, 0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x18,
|
||||
0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x6d, 0x65,
|
||||
0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x12, 0x53, 0x0a, 0x12, 0x62, 0x6c,
|
||||
0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73,
|
||||
0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
|
||||
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x52, 0x12, 0x62, 0x6c, 0x75,
|
||||
0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x22,
|
||||
0x6d, 0x0a, 0x14, 0x44, 0x62, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f,
|
||||
0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48,
|
||||
0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
||||
0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68,
|
||||
0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x28,
|
||||
0x0a, 0x0a, 0x44, 0x62, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08,
|
||||
0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08,
|
||||
0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x22, 0x46, 0x0a, 0x09, 0x44, 0x62, 0x55, 0x74,
|
||||
0x78, 0x6f, 0x53, 0x65, 0x74, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73,
|
||||
0x22, 0x87, 0x01, 0x0a, 0x14, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x6f, 0x75, 0x74,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x4f, 0x75,
|
||||
0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x12, 0x38, 0x0a, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
||||
0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x62,
|
||||
0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12,
|
||||
0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x22, 0xb9, 0x01, 0x0a, 0x0b, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c,
|
||||
0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1e, 0x0a,
|
||||
0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x22, 0xfe, 0x01,
|
||||
0x0a, 0x12, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79,
|
||||
0x44, 0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
|
||||
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x63,
|
||||
0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x2d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06,
|
||||
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
|
||||
0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
|
||||
0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68,
|
||||
0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x52,
|
||||
0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x43, 0x0a, 0x11, 0x66, 0x75, 0x74,
|
||||
0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x18, 0x04,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x11, 0x66, 0x75, 0x74,
|
||||
0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x22, 0x40,
|
||||
0x0a, 0x16, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79,
|
||||
0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72,
|
||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x65, 0x6e, 0x64,
|
||||
0x22, 0x88, 0x01, 0x0a, 0x0a, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x44, 0x69, 0x66, 0x66, 0x12,
|
||||
0x39, 0x0a, 0x05, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
|
||||
0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49,
|
||||
0x74, 0x65, 0x6d, 0x52, 0x05, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x12, 0x3f, 0x0a, 0x08, 0x74, 0x6f,
|
||||
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55,
|
||||
0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65,
|
||||
0x6d, 0x52, 0x08, 0x74, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x33, 0x0a, 0x06, 0x44,
|
||||
0x62, 0x54, 0x69, 0x70, 0x73, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x69, 0x70, 0x73, 0x18, 0x01, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x04, 0x74, 0x69, 0x70, 0x73,
|
||||
0x22, 0x24, 0x0a, 0x0c, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||
0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x2a, 0x0a, 0x12, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64,
|
||||
0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1895,37 +1907,38 @@ var file_dbobjects_proto_depIdxs = []int32{
|
||||
4, // 6: serialization.DbTransaction.inputs:type_name -> serialization.DbTransactionInput
|
||||
7, // 7: serialization.DbTransaction.outputs:type_name -> serialization.DbTransactionOutput
|
||||
8, // 8: serialization.DbTransaction.subnetworkID:type_name -> serialization.DbSubnetworkId
|
||||
5, // 9: serialization.DbTransactionInput.previousOutpoint:type_name -> serialization.DbOutpoint
|
||||
6, // 10: serialization.DbOutpoint.transactionID:type_name -> serialization.DbTransactionId
|
||||
19, // 11: serialization.DbTransactionOutput.scriptPublicKey:type_name -> serialization.DbScriptPublicKey
|
||||
10, // 12: serialization.DbAcceptanceData.blockAcceptanceData:type_name -> serialization.DbBlockAcceptanceData
|
||||
11, // 13: serialization.DbBlockAcceptanceData.transactionAcceptanceData:type_name -> serialization.DbTransactionAcceptanceData
|
||||
2, // 14: serialization.DbBlockAcceptanceData.blockHash:type_name -> serialization.DbHash
|
||||
3, // 15: serialization.DbTransactionAcceptanceData.transaction:type_name -> serialization.DbTransaction
|
||||
20, // 16: serialization.DbTransactionAcceptanceData.transactionInputUtxoEntries:type_name -> serialization.DbUtxoEntry
|
||||
2, // 17: serialization.DbBlockRelations.parents:type_name -> serialization.DbHash
|
||||
2, // 18: serialization.DbBlockRelations.children:type_name -> serialization.DbHash
|
||||
2, // 19: serialization.DbBlockGhostdagData.selectedParent:type_name -> serialization.DbHash
|
||||
2, // 20: serialization.DbBlockGhostdagData.mergeSetBlues:type_name -> serialization.DbHash
|
||||
2, // 21: serialization.DbBlockGhostdagData.mergeSetReds:type_name -> serialization.DbHash
|
||||
15, // 22: serialization.DbBlockGhostdagData.bluesAnticoneSizes:type_name -> serialization.DbBluesAnticoneSizes
|
||||
2, // 23: serialization.DbBluesAnticoneSizes.blueHash:type_name -> serialization.DbHash
|
||||
18, // 24: serialization.DbUtxoSet.items:type_name -> serialization.DbUtxoCollectionItem
|
||||
5, // 25: serialization.DbUtxoCollectionItem.outpoint:type_name -> serialization.DbOutpoint
|
||||
20, // 26: serialization.DbUtxoCollectionItem.utxoEntry:type_name -> serialization.DbUtxoEntry
|
||||
19, // 27: serialization.DbUtxoEntry.scriptPublicKey:type_name -> serialization.DbScriptPublicKey
|
||||
2, // 28: serialization.DbReachabilityData.children:type_name -> serialization.DbHash
|
||||
2, // 29: serialization.DbReachabilityData.parent:type_name -> serialization.DbHash
|
||||
22, // 30: serialization.DbReachabilityData.interval:type_name -> serialization.DbReachabilityInterval
|
||||
2, // 31: serialization.DbReachabilityData.futureCoveringSet:type_name -> serialization.DbHash
|
||||
18, // 32: serialization.DbUtxoDiff.toAdd:type_name -> serialization.DbUtxoCollectionItem
|
||||
18, // 33: serialization.DbUtxoDiff.toRemove:type_name -> serialization.DbUtxoCollectionItem
|
||||
2, // 34: serialization.DbTips.tips:type_name -> serialization.DbHash
|
||||
35, // [35:35] is the sub-list for method output_type
|
||||
35, // [35:35] is the sub-list for method input_type
|
||||
35, // [35:35] is the sub-list for extension type_name
|
||||
35, // [35:35] is the sub-list for extension extendee
|
||||
0, // [0:35] is the sub-list for field type_name
|
||||
2, // 9: serialization.DbTransaction.payloadHash:type_name -> serialization.DbHash
|
||||
5, // 10: serialization.DbTransactionInput.previousOutpoint:type_name -> serialization.DbOutpoint
|
||||
6, // 11: serialization.DbOutpoint.transactionID:type_name -> serialization.DbTransactionId
|
||||
19, // 12: serialization.DbTransactionOutput.scriptPublicKey:type_name -> serialization.DbScriptPublicKey
|
||||
10, // 13: serialization.DbAcceptanceData.blockAcceptanceData:type_name -> serialization.DbBlockAcceptanceData
|
||||
11, // 14: serialization.DbBlockAcceptanceData.transactionAcceptanceData:type_name -> serialization.DbTransactionAcceptanceData
|
||||
2, // 15: serialization.DbBlockAcceptanceData.blockHash:type_name -> serialization.DbHash
|
||||
3, // 16: serialization.DbTransactionAcceptanceData.transaction:type_name -> serialization.DbTransaction
|
||||
20, // 17: serialization.DbTransactionAcceptanceData.transactionInputUtxoEntries:type_name -> serialization.DbUtxoEntry
|
||||
2, // 18: serialization.DbBlockRelations.parents:type_name -> serialization.DbHash
|
||||
2, // 19: serialization.DbBlockRelations.children:type_name -> serialization.DbHash
|
||||
2, // 20: serialization.DbBlockGhostdagData.selectedParent:type_name -> serialization.DbHash
|
||||
2, // 21: serialization.DbBlockGhostdagData.mergeSetBlues:type_name -> serialization.DbHash
|
||||
2, // 22: serialization.DbBlockGhostdagData.mergeSetReds:type_name -> serialization.DbHash
|
||||
15, // 23: serialization.DbBlockGhostdagData.bluesAnticoneSizes:type_name -> serialization.DbBluesAnticoneSizes
|
||||
2, // 24: serialization.DbBluesAnticoneSizes.blueHash:type_name -> serialization.DbHash
|
||||
18, // 25: serialization.DbUtxoSet.items:type_name -> serialization.DbUtxoCollectionItem
|
||||
5, // 26: serialization.DbUtxoCollectionItem.outpoint:type_name -> serialization.DbOutpoint
|
||||
20, // 27: serialization.DbUtxoCollectionItem.utxoEntry:type_name -> serialization.DbUtxoEntry
|
||||
19, // 28: serialization.DbUtxoEntry.scriptPublicKey:type_name -> serialization.DbScriptPublicKey
|
||||
2, // 29: serialization.DbReachabilityData.children:type_name -> serialization.DbHash
|
||||
2, // 30: serialization.DbReachabilityData.parent:type_name -> serialization.DbHash
|
||||
22, // 31: serialization.DbReachabilityData.interval:type_name -> serialization.DbReachabilityInterval
|
||||
2, // 32: serialization.DbReachabilityData.futureCoveringSet:type_name -> serialization.DbHash
|
||||
18, // 33: serialization.DbUtxoDiff.toAdd:type_name -> serialization.DbUtxoCollectionItem
|
||||
18, // 34: serialization.DbUtxoDiff.toRemove:type_name -> serialization.DbUtxoCollectionItem
|
||||
2, // 35: serialization.DbTips.tips:type_name -> serialization.DbHash
|
||||
36, // [36:36] is the sub-list for method output_type
|
||||
36, // [36:36] is the sub-list for method input_type
|
||||
36, // [36:36] is the sub-list for extension type_name
|
||||
36, // [36:36] is the sub-list for extension extendee
|
||||
0, // [0:36] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_dbobjects_proto_init() }
|
||||
|
||||
@@ -30,6 +30,7 @@ message DbTransaction {
|
||||
uint64 lockTime = 4;
|
||||
DbSubnetworkId subnetworkID = 5;
|
||||
uint64 gas = 6;
|
||||
DbHash payloadHash = 7;
|
||||
bytes payload = 8;
|
||||
}
|
||||
|
||||
@@ -117,7 +118,7 @@ message DbScriptPublicKey {
|
||||
message DbUtxoEntry {
|
||||
uint64 amount = 1;
|
||||
DbScriptPublicKey scriptPublicKey = 2;
|
||||
uint64 blockDaaScore = 3;
|
||||
uint64 blockBlueScore = 3;
|
||||
bool isCoinbase = 4;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ func DomainTransactionToDbTransaction(domainTransaction *externalapi.DomainTrans
|
||||
LockTime: domainTransaction.LockTime,
|
||||
SubnetworkID: DomainSubnetworkIDToDbSubnetworkID(&domainTransaction.SubnetworkID),
|
||||
Gas: domainTransaction.Gas,
|
||||
PayloadHash: DomainHashToDbHash(&domainTransaction.PayloadHash),
|
||||
Payload: domainTransaction.Payload,
|
||||
}
|
||||
}
|
||||
@@ -43,6 +44,10 @@ func DbTransactionToDomainTransaction(dbTransaction *DbTransaction) (*externalap
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domainPayloadHash, err := DbHashToDomainHash(dbTransaction.PayloadHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domainInputs := make([]*externalapi.DomainTransactionInput, len(dbTransaction.Inputs))
|
||||
for i, dbTransactionInput := range dbTransaction.Inputs {
|
||||
@@ -79,6 +84,7 @@ func DbTransactionToDomainTransaction(dbTransaction *DbTransaction) (*externalap
|
||||
LockTime: dbTransaction.LockTime,
|
||||
SubnetworkID: *domainSubnetworkID,
|
||||
Gas: dbTransaction.Gas,
|
||||
PayloadHash: *domainPayloadHash,
|
||||
Payload: dbTransaction.Payload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func UTXOEntryToDBUTXOEntry(utxoEntry externalapi.UTXOEntry) *DbUtxoEntry {
|
||||
return &DbUtxoEntry{
|
||||
Amount: utxoEntry.Amount(),
|
||||
ScriptPublicKey: dbScriptPublicKey,
|
||||
BlockDaaScore: utxoEntry.BlockDAAScore(),
|
||||
BlockBlueScore: utxoEntry.BlockBlueScore(),
|
||||
IsCoinbase: utxoEntry.IsCoinbase(),
|
||||
}
|
||||
}
|
||||
@@ -37,5 +37,5 @@ func DBUTXOEntryToUTXOEntry(dbUtxoEntry *DbUtxoEntry) (externalapi.UTXOEntry, er
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utxo.NewUTXOEntry(dbUtxoEntry.Amount, scriptPublicKey, dbUtxoEntry.IsCoinbase, dbUtxoEntry.BlockDaaScore), nil
|
||||
return utxo.NewUTXOEntry(dbUtxoEntry.Amount, scriptPublicKey, dbUtxoEntry.IsCoinbase, dbUtxoEntry.BlockBlueScore), nil
|
||||
}
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
package daablocksstore
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/database"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/database/binaryserialization"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/lrucache"
|
||||
)
|
||||
|
||||
var daaScoreBucket = database.MakeBucket([]byte("daa-score"))
|
||||
var daaAddedBlocksBucket = database.MakeBucket([]byte("daa-added-blocks"))
|
||||
|
||||
// daaBlocksStore represents a store of DAABlocksStore
|
||||
type daaBlocksStore struct {
|
||||
daaScoreStaging map[externalapi.DomainHash]uint64
|
||||
daaAddedBlocksStaging map[externalapi.DomainHash][]*externalapi.DomainHash
|
||||
daaScoreToDelete map[externalapi.DomainHash]struct{}
|
||||
daaAddedBlocksToDelete map[externalapi.DomainHash]struct{}
|
||||
daaScoreLRUCache *lrucache.LRUCache
|
||||
daaAddedBlocksLRUCache *lrucache.LRUCache
|
||||
}
|
||||
|
||||
// New instantiates a new DAABlocksStore
|
||||
func New(daaScoreCacheSize int, daaAddedBlocksCacheSize int, preallocate bool) model.DAABlocksStore {
|
||||
return &daaBlocksStore{
|
||||
daaScoreStaging: make(map[externalapi.DomainHash]uint64),
|
||||
daaAddedBlocksStaging: make(map[externalapi.DomainHash][]*externalapi.DomainHash),
|
||||
daaScoreLRUCache: lrucache.New(daaScoreCacheSize, preallocate),
|
||||
daaAddedBlocksLRUCache: lrucache.New(daaAddedBlocksCacheSize, preallocate),
|
||||
}
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) StageDAAScore(blockHash *externalapi.DomainHash, daaScore uint64) {
|
||||
daas.daaScoreStaging[*blockHash] = daaScore
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) StageBlockDAAAddedBlocks(blockHash *externalapi.DomainHash,
|
||||
addedBlocks []*externalapi.DomainHash) {
|
||||
daas.daaAddedBlocksStaging[*blockHash] = externalapi.CloneHashes(addedBlocks)
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) IsAnythingStaged() bool {
|
||||
return len(daas.daaScoreStaging) != 0 ||
|
||||
len(daas.daaAddedBlocksStaging) != 0 ||
|
||||
len(daas.daaScoreToDelete) != 0 ||
|
||||
len(daas.daaAddedBlocksToDelete) != 0
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) Discard() {
|
||||
daas.daaScoreStaging = make(map[externalapi.DomainHash]uint64)
|
||||
daas.daaAddedBlocksStaging = make(map[externalapi.DomainHash][]*externalapi.DomainHash)
|
||||
daas.daaScoreToDelete = make(map[externalapi.DomainHash]struct{})
|
||||
daas.daaAddedBlocksToDelete = make(map[externalapi.DomainHash]struct{})
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) Commit(dbTx model.DBTransaction) error {
|
||||
for hash, daaScore := range daas.daaScoreStaging {
|
||||
daaScoreBytes := binaryserialization.SerializeUint64(daaScore)
|
||||
err := dbTx.Put(daas.daaScoreHashAsKey(&hash), daaScoreBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
daas.daaScoreLRUCache.Add(&hash, daaScore)
|
||||
}
|
||||
|
||||
for hash, addedBlocks := range daas.daaAddedBlocksStaging {
|
||||
addedBlocksBytes := binaryserialization.SerializeHashes(addedBlocks)
|
||||
err := dbTx.Put(daas.daaAddedBlocksHashAsKey(&hash), addedBlocksBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
daas.daaAddedBlocksLRUCache.Add(&hash, addedBlocks)
|
||||
}
|
||||
|
||||
for hash := range daas.daaScoreToDelete {
|
||||
err := dbTx.Delete(daas.daaScoreHashAsKey(&hash))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
daas.daaScoreLRUCache.Remove(&hash)
|
||||
}
|
||||
|
||||
for hash := range daas.daaAddedBlocksToDelete {
|
||||
err := dbTx.Delete(daas.daaAddedBlocksHashAsKey(&hash))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
daas.daaAddedBlocksLRUCache.Remove(&hash)
|
||||
}
|
||||
|
||||
daas.Discard()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) DAAScore(dbContext model.DBReader, blockHash *externalapi.DomainHash) (uint64, error) {
|
||||
if daaScore, ok := daas.daaScoreStaging[*blockHash]; ok {
|
||||
return daaScore, nil
|
||||
}
|
||||
|
||||
if daaScore, ok := daas.daaScoreLRUCache.Get(blockHash); ok {
|
||||
return daaScore.(uint64), nil
|
||||
}
|
||||
|
||||
daaScoreBytes, err := dbContext.Get(daas.daaScoreHashAsKey(blockHash))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
daaScore, err := binaryserialization.DeserializeUint64(daaScoreBytes)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
daas.daaScoreLRUCache.Add(blockHash, daaScore)
|
||||
return daaScore, nil
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) DAAAddedBlocks(dbContext model.DBReader, blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
||||
if addedBlocks, ok := daas.daaAddedBlocksStaging[*blockHash]; ok {
|
||||
return externalapi.CloneHashes(addedBlocks), nil
|
||||
}
|
||||
|
||||
if addedBlocks, ok := daas.daaAddedBlocksLRUCache.Get(blockHash); ok {
|
||||
return externalapi.CloneHashes(addedBlocks.([]*externalapi.DomainHash)), nil
|
||||
}
|
||||
|
||||
addedBlocksBytes, err := dbContext.Get(daas.daaAddedBlocksHashAsKey(blockHash))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addedBlocks, err := binaryserialization.DeserializeHashes(addedBlocksBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
daas.daaAddedBlocksLRUCache.Add(blockHash, addedBlocks)
|
||||
return externalapi.CloneHashes(addedBlocks), nil
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) daaScoreHashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
||||
return daaScoreBucket.Key(hash.ByteSlice())
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) daaAddedBlocksHashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
||||
return daaAddedBlocksBucket.Key(hash.ByteSlice())
|
||||
}
|
||||
|
||||
func (daas *daaBlocksStore) Delete(blockHash *externalapi.DomainHash) {
|
||||
if _, ok := daas.daaScoreStaging[*blockHash]; ok {
|
||||
delete(daas.daaScoreStaging, *blockHash)
|
||||
} else {
|
||||
daas.daaAddedBlocksToDelete[*blockHash] = struct{}{}
|
||||
}
|
||||
|
||||
if _, ok := daas.daaAddedBlocksStaging[*blockHash]; ok {
|
||||
delete(daas.daaAddedBlocksStaging, *blockHash)
|
||||
} else {
|
||||
daas.daaAddedBlocksToDelete[*blockHash] = struct{}{}
|
||||
}
|
||||
}
|
||||
@@ -161,11 +161,7 @@ func (hscs *headersSelectedChainStore) GetIndexByHash(dbContext model.DBReader,
|
||||
return 0, err
|
||||
}
|
||||
|
||||
index, err := hscs.deserializeIndex(indexBytes)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
index := hscs.deserializeIndex(indexBytes)
|
||||
hscs.cacheByHash.Add(blockHash, index)
|
||||
return index, nil
|
||||
}
|
||||
@@ -197,11 +193,11 @@ func (hscs *headersSelectedChainStore) GetHashByIndex(dbContext model.DBReader,
|
||||
}
|
||||
|
||||
func (hscs *headersSelectedChainStore) serializeIndex(index uint64) []byte {
|
||||
return binaryserialization.SerializeUint64(index)
|
||||
return binaryserialization.SerializeChainBlockIndex(index)
|
||||
}
|
||||
|
||||
func (hscs *headersSelectedChainStore) deserializeIndex(indexBytes []byte) (uint64, error) {
|
||||
return binaryserialization.DeserializeUint64(indexBytes)
|
||||
func (hscs *headersSelectedChainStore) deserializeIndex(indexBytes []byte) uint64 {
|
||||
return binaryserialization.DeserializeChainBlockIndex(indexBytes)
|
||||
}
|
||||
|
||||
func (hscs *headersSelectedChainStore) hashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
||||
@@ -227,11 +223,7 @@ func (hscs *headersSelectedChainStore) highestChainBlockIndex(dbContext model.DB
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
index, err := hscs.deserializeIndex(indexBytes)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
index := hscs.deserializeIndex(indexBytes)
|
||||
hscs.cacheHighestChainBlockIndex = index
|
||||
return index, true, nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
daablocksstore "github.com/kaspanet/kaspad/domain/consensus/datastructures/daablocksstore"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
@@ -127,7 +126,6 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
headersSelectedTipStore := headersselectedtipstore.New()
|
||||
finalityStore := finalitystore.New(200, preallocateCaches)
|
||||
headersSelectedChainStore := headersselectedchainstore.New(pruningWindowSizeForCaches, preallocateCaches)
|
||||
daaBlocksStore := daablocksstore.New(pruningWindowSizeForCaches, int(dagParams.FinalityDepth()), preallocateCaches)
|
||||
|
||||
// Processes
|
||||
reachabilityManager := reachabilitymanager.New(
|
||||
@@ -151,15 +149,13 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
ghostdagDataStore,
|
||||
reachabilityDataStore,
|
||||
ghostdagManager,
|
||||
consensusStateStore,
|
||||
dagParams.GenesisHash)
|
||||
consensusStateStore)
|
||||
pastMedianTimeManager := f.pastMedianTimeConsructor(
|
||||
dagParams.TimestampDeviationTolerance,
|
||||
dbManager,
|
||||
dagTraversalManager,
|
||||
blockHeaderStore,
|
||||
ghostdagDataStore,
|
||||
dagParams.GenesisHash)
|
||||
ghostdagDataStore)
|
||||
transactionValidator := transactionvalidator.New(dagParams.BlockCoinbaseMaturity,
|
||||
dagParams.EnableNonNativeSubnetworks,
|
||||
dagParams.MassPerTxByte,
|
||||
@@ -168,14 +164,12 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
dagParams.MaxCoinbasePayloadLength,
|
||||
dbManager,
|
||||
pastMedianTimeManager,
|
||||
ghostdagDataStore,
|
||||
daaBlocksStore)
|
||||
ghostdagDataStore)
|
||||
difficultyManager := f.difficultyConstructor(
|
||||
dbManager,
|
||||
ghostdagManager,
|
||||
ghostdagDataStore,
|
||||
blockHeaderStore,
|
||||
daaBlocksStore,
|
||||
dagTopologyManager,
|
||||
dagTraversalManager,
|
||||
dagParams.PowMax,
|
||||
@@ -189,8 +183,7 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
dagParams.BaseSubsidy,
|
||||
dagParams.CoinbasePayloadScriptPublicKeyMaxLength,
|
||||
ghostdagDataStore,
|
||||
acceptanceDataStore,
|
||||
daaBlocksStore)
|
||||
acceptanceDataStore)
|
||||
headerTipsManager := headersselectedtipmanager.New(dbManager, dagTopologyManager, dagTraversalManager,
|
||||
ghostdagManager, headersSelectedTipStore, headersSelectedChainStore)
|
||||
genesisHash := dagParams.GenesisHash
|
||||
@@ -255,7 +248,6 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
coinbaseManager,
|
||||
mergeDepthManager,
|
||||
finalityManager,
|
||||
difficultyManager,
|
||||
|
||||
blockStatusStore,
|
||||
ghostdagDataStore,
|
||||
@@ -267,8 +259,7 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
acceptanceDataStore,
|
||||
blockHeaderStore,
|
||||
headersSelectedTipStore,
|
||||
pruningStore,
|
||||
daaBlocksStore)
|
||||
pruningStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -288,7 +279,6 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
blockStore,
|
||||
blockHeaderStore,
|
||||
utxoDiffStore,
|
||||
daaBlocksStore,
|
||||
isArchivalNode,
|
||||
genesisHash,
|
||||
dagParams.FinalityDepth(),
|
||||
@@ -353,8 +343,7 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
blockHeaderStore,
|
||||
headersSelectedTipStore,
|
||||
finalityStore,
|
||||
headersSelectedChainStore,
|
||||
daaBlocksStore)
|
||||
headersSelectedChainStore)
|
||||
|
||||
c := &consensus{
|
||||
lock: &sync.Mutex{},
|
||||
@@ -392,7 +381,6 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
utxoDiffStore: utxoDiffStore,
|
||||
finalityStore: finalityStore,
|
||||
headersSelectedChainStore: headersSelectedChainStore,
|
||||
daaBlocksStore: daaBlocksStore,
|
||||
}
|
||||
|
||||
genesisInfo, err := c.GetBlockInfo(genesisHash)
|
||||
|
||||
@@ -26,9 +26,14 @@ func initTestTransactionAcceptanceDataForClone() []*externalapi.TransactionAccep
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -70,9 +75,14 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -99,9 +109,14 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -127,9 +142,14 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -155,9 +175,14 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -184,9 +209,14 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -214,9 +244,14 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -319,6 +354,11 @@ func initTestBlockAcceptanceDataForClone() []*externalapi.BlockAcceptanceData {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -366,6 +406,11 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -398,6 +443,11 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -430,6 +480,11 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -462,6 +517,11 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -495,6 +555,11 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -598,6 +663,11 @@ func initTestAcceptanceDataForClone() []externalapi.AcceptanceData {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -647,6 +717,11 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -679,6 +754,11 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -711,6 +791,11 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -743,6 +828,11 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
|
||||
@@ -26,9 +26,14 @@ func initTestBaseTransactions() []*externalapi.DomainTransaction {
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -47,9 +52,14 @@ func initTestAnotherTransactions() []*externalapi.DomainTransaction {
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x02},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -68,9 +78,14 @@ func initTestTwoTransactions() []*externalapi.DomainTransaction {
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -83,9 +98,14 @@ func initTestTwoTransactions() []*externalapi.DomainTransaction {
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
@@ -12,7 +12,7 @@ type Consensus interface {
|
||||
GetBlockChildren(blockHash *DomainHash) ([]*DomainHash, error)
|
||||
GetBlockAcceptanceData(blockHash *DomainHash) (AcceptanceData, error)
|
||||
|
||||
GetHashesBetween(lowHash, highHash *DomainHash, maxBlueScoreDifference uint64) (hashes []*DomainHash, actualHighHash *DomainHash, err error)
|
||||
GetHashesBetween(lowHash, highHash *DomainHash, maxBlueScoreDifference uint64) ([]*DomainHash, error)
|
||||
GetMissingBlockBodyHashes(highHash *DomainHash) ([]*DomainHash, error)
|
||||
GetPruningPointUTXOs(expectedPruningPointHash *DomainHash, fromOutpoint *DomainOutpoint, limit int) ([]*OutpointAndUTXOEntryPair, error)
|
||||
GetVirtualUTXOs(expectedVirtualParents []*DomainHash, fromOutpoint *DomainOutpoint, limit int) ([]*OutpointAndUTXOEntryPair, error)
|
||||
|
||||
@@ -15,11 +15,6 @@ type DomainHash struct {
|
||||
hashArray [DomainHashSize]byte
|
||||
}
|
||||
|
||||
// NewZeroHash returns a DomainHash that represents the zero value (0x000000...000)
|
||||
func NewZeroHash() *DomainHash {
|
||||
return &DomainHash{hashArray: [32]byte{}}
|
||||
}
|
||||
|
||||
// NewDomainHashFromByteArray constructs a new DomainHash out of a byte array
|
||||
func NewDomainHashFromByteArray(hashBytes *[DomainHashSize]byte) *DomainHash {
|
||||
return &DomainHash{
|
||||
|
||||
@@ -15,6 +15,7 @@ type DomainTransaction struct {
|
||||
LockTime uint64
|
||||
SubnetworkID DomainSubnetworkID
|
||||
Gas uint64
|
||||
PayloadHash DomainHash
|
||||
Payload []byte
|
||||
|
||||
Fee uint64
|
||||
@@ -52,6 +53,7 @@ func (tx *DomainTransaction) Clone() *DomainTransaction {
|
||||
LockTime: tx.LockTime,
|
||||
SubnetworkID: *tx.SubnetworkID.Clone(),
|
||||
Gas: tx.Gas,
|
||||
PayloadHash: tx.PayloadHash,
|
||||
Payload: payloadClone,
|
||||
Fee: tx.Fee,
|
||||
Mass: tx.Mass,
|
||||
@@ -62,7 +64,7 @@ func (tx *DomainTransaction) Clone() *DomainTransaction {
|
||||
// If this doesn't compile, it means the type definition has been changed, so it's
|
||||
// an indication to update Equal and Clone accordingly.
|
||||
var _ = DomainTransaction{0, []*DomainTransactionInput{}, []*DomainTransactionOutput{}, 0,
|
||||
DomainSubnetworkID{}, 0, []byte{}, 0, 0,
|
||||
DomainSubnetworkID{}, 0, DomainHash{}, []byte{}, 0, 0,
|
||||
&DomainTransactionID{}}
|
||||
|
||||
// Equal returns whether tx equals to other
|
||||
@@ -107,6 +109,10 @@ func (tx *DomainTransaction) Equal(other *DomainTransaction) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if !tx.PayloadHash.Equal(&other.PayloadHash) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !bytes.Equal(tx.Payload, other.Payload) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@ func initTestBaseTransaction() *externalapi.DomainTransaction {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -93,6 +97,34 @@ func initTestBaseTransaction() *externalapi.DomainTransaction {
|
||||
func initTestTransactionToCompare() []*transactionToCompare {
|
||||
|
||||
testTx := []*transactionToCompare{{
|
||||
tx: &externalapi.DomainTransaction{
|
||||
1,
|
||||
[]*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
|
||||
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
|
||||
[]byte{1, 2, 3},
|
||||
uint64(0xFFFFFFFF),
|
||||
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
|
||||
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
|
||||
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
|
||||
{uint64(0xFFFF),
|
||||
&externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}},
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), //Changed
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}),
|
||||
},
|
||||
expectedResult: false,
|
||||
}, {
|
||||
tx: &externalapi.DomainTransaction{
|
||||
1,
|
||||
[]*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
|
||||
@@ -107,6 +139,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -131,6 +167,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01, 0x02}, //Changed
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -155,6 +195,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01, 0x02}, //Changed
|
||||
0,
|
||||
1,
|
||||
@@ -178,6 +222,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -204,6 +252,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -229,6 +281,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
1000000000, //Changed
|
||||
1,
|
||||
@@ -252,6 +308,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -275,6 +335,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
2, //Changed
|
||||
@@ -298,6 +362,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
2, //Changed
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -326,6 +394,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -350,6 +422,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -373,6 +449,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -393,6 +473,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -418,6 +502,10 @@ func initTestTransactionToCompare() []*transactionToCompare {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
2, // Changed
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
@@ -449,9 +537,13 @@ func initTestDomainTransactionForClone() []*externalapi.DomainTransaction {
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 5555555555,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 5555555555,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -463,10 +555,14 @@ func initTestDomainTransactionForClone() []*externalapi.DomainTransaction {
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{}),
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{}),
|
||||
},
|
||||
}
|
||||
return tests
|
||||
@@ -482,6 +578,27 @@ func initTestDomainTransactionForEqual() []testDomainTransactionStruct {
|
||||
{
|
||||
baseTx: nil,
|
||||
transactionToCompareTo: []*transactionToCompare{{
|
||||
tx: &externalapi.DomainTransaction{
|
||||
1,
|
||||
[]*externalapi.DomainTransactionInput{},
|
||||
[]*externalapi.DomainTransactionOutput{},
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
0,
|
||||
1,
|
||||
externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}),
|
||||
},
|
||||
expectedResult: false,
|
||||
}, {
|
||||
tx: nil,
|
||||
expectedResult: true}},
|
||||
}, {
|
||||
@@ -492,6 +609,10 @@ func initTestDomainTransactionForEqual() []testDomainTransactionStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
1,
|
||||
1,
|
||||
@@ -511,6 +632,10 @@ func initTestDomainTransactionForEqual() []testDomainTransactionStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
0,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
1,
|
||||
1,
|
||||
@@ -525,6 +650,10 @@ func initTestDomainTransactionForEqual() []testDomainTransactionStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
1,
|
||||
1,
|
||||
@@ -539,6 +668,10 @@ func initTestDomainTransactionForEqual() []testDomainTransactionStruct {
|
||||
1,
|
||||
externalapi.DomainSubnetworkID{0x01},
|
||||
1,
|
||||
*externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
[]byte{0x01},
|
||||
2, // Changed fee
|
||||
1,
|
||||
|
||||
@@ -27,5 +27,5 @@ type MutableUTXODiff interface {
|
||||
ToRemove() UTXOCollection
|
||||
|
||||
WithDiffInPlace(other UTXODiff) error
|
||||
AddTransaction(transaction *DomainTransaction, blockDAAScore uint64) error
|
||||
AddTransaction(transaction *DomainTransaction, blockBlueScore uint64) error
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package externalapi
|
||||
type UTXOEntry interface {
|
||||
Amount() uint64
|
||||
ScriptPublicKey() *ScriptPublicKey // The public key script for the output.
|
||||
BlockDAAScore() uint64 // Blue score of the block accepting the tx.
|
||||
BlockBlueScore() uint64 // Blue score of the block accepting the tx.
|
||||
IsCoinbase() bool
|
||||
Equal(other UTXOEntry) bool
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package model
|
||||
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
// DAABlocksStore represents a store of ???
|
||||
type DAABlocksStore interface {
|
||||
Store
|
||||
StageDAAScore(blockHash *externalapi.DomainHash, daaScore uint64)
|
||||
StageBlockDAAAddedBlocks(blockHash *externalapi.DomainHash, addedBlocks []*externalapi.DomainHash)
|
||||
IsAnythingStaged() bool
|
||||
DAAAddedBlocks(dbContext DBReader, blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error)
|
||||
DAAScore(dbContext DBReader, blockHash *externalapi.DomainHash) (uint64, error)
|
||||
Delete(blockHash *externalapi.DomainHash)
|
||||
}
|
||||
@@ -5,6 +5,5 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
// DifficultyManager provides a method to resolve the
|
||||
// difficulty value of a block
|
||||
type DifficultyManager interface {
|
||||
StageDAADataAndReturnRequiredDifficulty(blockHash *externalapi.DomainHash) (uint32, error)
|
||||
RequiredDifficulty(blockHash *externalapi.DomainHash) (uint32, error)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
// SyncManager exposes functions to support sync between kaspad nodes
|
||||
type SyncManager interface {
|
||||
GetHashesBetween(lowHash, highHash *externalapi.DomainHash, maxBlueScoreDifference uint64) (
|
||||
hashes []*externalapi.DomainHash, actualHighHash *externalapi.DomainHash, err error)
|
||||
GetHashesBetween(lowHash, highHash *externalapi.DomainHash, maxBlueScoreDifference uint64) ([]*externalapi.DomainHash, error)
|
||||
GetMissingBlockBodyHashes(highHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error)
|
||||
CreateBlockLocator(lowHash, highHash *externalapi.DomainHash, limit uint32) (externalapi.BlockLocator, error)
|
||||
CreateHeadersSelectedChainBlockLocator(lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error)
|
||||
|
||||
@@ -66,7 +66,6 @@ type TestConsensus interface {
|
||||
ReachabilityDataStore() model.ReachabilityDataStore
|
||||
UTXODiffStore() model.UTXODiffStore
|
||||
HeadersSelectedChainStore() model.HeadersSelectedChainStore
|
||||
DAABlocksStore() model.DAABlocksStore
|
||||
|
||||
BlockBuilder() TestBlockBuilder
|
||||
BlockProcessor() model.BlockProcessor
|
||||
|
||||
@@ -71,6 +71,7 @@ func TestBuildBlockErrorCases(t *testing.T) {
|
||||
LockTime: 0,
|
||||
SubnetworkID: subnetworks.SubnetworkIDNative,
|
||||
Gas: 0,
|
||||
PayloadHash: externalapi.DomainHash{},
|
||||
Payload: []byte{0},
|
||||
},
|
||||
{
|
||||
@@ -85,6 +86,7 @@ func TestBuildBlockErrorCases(t *testing.T) {
|
||||
LockTime: 0,
|
||||
SubnetworkID: subnetworks.SubnetworkIDNative,
|
||||
Gas: 0,
|
||||
PayloadHash: externalapi.DomainHash{},
|
||||
Payload: []byte{1},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -62,13 +62,18 @@ func (bb *testBlockBuilder) BuildBlockWithParents(parentHashes []*externalapi.Do
|
||||
}
|
||||
|
||||
func (bb *testBlockBuilder) buildUTXOInvalidHeader(parentHashes []*externalapi.DomainHash,
|
||||
bits uint32, transactions []*externalapi.DomainTransaction) (externalapi.BlockHeader, error) {
|
||||
transactions []*externalapi.DomainTransaction) (externalapi.BlockHeader, error) {
|
||||
|
||||
timeInMilliseconds, err := bb.minBlockTime(tempBlockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bits, err := bb.difficultyManager.RequiredDifficulty(tempBlockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hashMerkleRoot := bb.newBlockHashMerkleRoot(transactions)
|
||||
|
||||
bb.nonceCounter++
|
||||
@@ -84,11 +89,11 @@ func (bb *testBlockBuilder) buildUTXOInvalidHeader(parentHashes []*externalapi.D
|
||||
), nil
|
||||
}
|
||||
|
||||
func (bb *testBlockBuilder) buildHeaderWithParents(parentHashes []*externalapi.DomainHash, bits uint32,
|
||||
func (bb *testBlockBuilder) buildHeaderWithParents(parentHashes []*externalapi.DomainHash,
|
||||
transactions []*externalapi.DomainTransaction, acceptanceData externalapi.AcceptanceData, multiset model.Multiset) (
|
||||
externalapi.BlockHeader, error) {
|
||||
|
||||
header, err := bb.buildUTXOInvalidHeader(parentHashes, bits, transactions)
|
||||
header, err := bb.buildUTXOInvalidHeader(parentHashes, transactions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -131,11 +136,6 @@ func (bb *testBlockBuilder) buildBlockWithParents(parentHashes []*externalapi.Do
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
bits, err := bb.difficultyManager.StageDAADataAndReturnRequiredDifficulty(tempBlockHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ghostdagData, err := bb.ghostdagDataStore.Get(bb.databaseContext, tempBlockHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -163,7 +163,7 @@ func (bb *testBlockBuilder) buildBlockWithParents(parentHashes []*externalapi.Do
|
||||
}
|
||||
transactionsWithCoinbase := append([]*externalapi.DomainTransaction{coinbase}, transactions...)
|
||||
|
||||
header, err := bb.buildHeaderWithParents(parentHashes, bits, transactionsWithCoinbase, acceptanceData, multiset)
|
||||
header, err := bb.buildHeaderWithParents(parentHashes, transactionsWithCoinbase, acceptanceData, multiset)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -199,13 +199,7 @@ func (bb *testBlockBuilder) BuildUTXOInvalidBlock(parentHashes []*externalapi.Do
|
||||
|
||||
// We use genesis transactions so we'll have something to build merkle root and coinbase with
|
||||
genesisTransactions := bb.testConsensus.DAGParams().GenesisBlock.Transactions
|
||||
|
||||
bits, err := bb.difficultyManager.RequiredDifficulty(tempBlockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header, err := bb.buildUTXOInvalidHeader(parentHashes, bits, genesisTransactions)
|
||||
header, err := bb.buildUTXOInvalidHeader(parentHashes, genesisTransactions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ type blockProcessor struct {
|
||||
headersSelectedTipStore model.HeaderSelectedTipStore
|
||||
finalityStore model.FinalityStore
|
||||
headersSelectedChainStore model.HeadersSelectedChainStore
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
|
||||
stores []model.Store
|
||||
}
|
||||
@@ -79,7 +78,6 @@ func New(
|
||||
headersSelectedTipStore model.HeaderSelectedTipStore,
|
||||
finalityStore model.FinalityStore,
|
||||
headersSelectedChainStore model.HeadersSelectedChainStore,
|
||||
daaBlocksStore model.DAABlocksStore,
|
||||
) model.BlockProcessor {
|
||||
|
||||
return &blockProcessor{
|
||||
@@ -113,7 +111,6 @@ func New(
|
||||
headersSelectedTipStore: headersSelectedTipStore,
|
||||
finalityStore: finalityStore,
|
||||
headersSelectedChainStore: headersSelectedChainStore,
|
||||
daaBlocksStore: daaBlocksStore,
|
||||
|
||||
stores: []model.Store{
|
||||
consensusStateStore,
|
||||
@@ -131,7 +128,6 @@ func New(
|
||||
headersSelectedTipStore,
|
||||
finalityStore,
|
||||
headersSelectedChainStore,
|
||||
daaBlocksStore,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,9 +199,13 @@ func initData(params *dagconfig.Params) (*externalapi.DomainHash, externalapi.Do
|
||||
LockTime: 1,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
|
||||
Gas: 1,
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
Fee: 0,
|
||||
Mass: 1,
|
||||
ID: externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
@@ -440,11 +440,11 @@ func TestGetPruningPointUTXOs(t *testing.T) {
|
||||
Version: 0,
|
||||
},
|
||||
}
|
||||
blockAboveGenesis, err := testConsensus.BuildBlock(emptyCoinbase, nil)
|
||||
blockAboveGeneis, err := testConsensus.BuildBlock(emptyCoinbase, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error building block above genesis: %+v", err)
|
||||
}
|
||||
_, err = testConsensus.ValidateAndInsertBlock(blockAboveGenesis)
|
||||
_, err = testConsensus.ValidateAndInsertBlock(blockAboveGeneis)
|
||||
if err != nil {
|
||||
t.Fatalf("Error validating and inserting block above genesis: %+v", err)
|
||||
}
|
||||
@@ -476,7 +476,7 @@ func TestGetPruningPointUTXOs(t *testing.T) {
|
||||
Sequence: constants.MaxTxInSequenceNum,
|
||||
}
|
||||
|
||||
outputs := make([]*externalapi.DomainTransactionOutput, 900)
|
||||
outputs := make([]*externalapi.DomainTransactionOutput, 1125)
|
||||
for i := 0; i < len(outputs); i++ {
|
||||
outputs[i] = &externalapi.DomainTransactionOutput{
|
||||
ScriptPublicKey: scriptPublicKey,
|
||||
@@ -524,15 +524,6 @@ func TestGetPruningPointUTXOs(t *testing.T) {
|
||||
t.Fatalf("Error getting the pruning point: %+v", err)
|
||||
}
|
||||
|
||||
pruningRelations, err := testConsensus.BlockRelationStore().BlockRelation(testConsensus.DatabaseContext(), pruningPoint)
|
||||
if err != nil {
|
||||
t.Fatalf("BlockRelation(): %+v", err)
|
||||
}
|
||||
|
||||
if len(pruningRelations.Parents) != 1 && pruningRelations.Parents[0] != consensushashing.BlockHash(includingBlock) {
|
||||
t.Fatalf("includingBlock should be pruning point's only parent")
|
||||
}
|
||||
|
||||
// Get pruning point UTXOs in a loop
|
||||
var allOutpointAndUTXOEntryPairs []*externalapi.OutpointAndUTXOEntryPair
|
||||
step := 100
|
||||
@@ -550,9 +541,8 @@ func TestGetPruningPointUTXOs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the length of the UTXOs is exactly spendingTransaction.Outputs + 1 coinbase
|
||||
// output (includingBlock's coinbase)
|
||||
if len(allOutpointAndUTXOEntryPairs) != len(outputs)+1 {
|
||||
// Make sure the length of the UTXOs is exactly spendingTransaction.Outputs + 2 coinbase outputs
|
||||
if len(allOutpointAndUTXOEntryPairs) != len(outputs)+2 {
|
||||
t.Fatalf("Returned an unexpected amount of UTXOs. "+
|
||||
"Want: %d, got: %d", len(outputs)+2, len(allOutpointAndUTXOEntryPairs))
|
||||
}
|
||||
@@ -619,7 +609,7 @@ func BenchmarkGetPruningPointUTXOs(b *testing.B) {
|
||||
SignatureScript: signatureScript,
|
||||
Sequence: constants.MaxTxInSequenceNum,
|
||||
}
|
||||
outputs := make([]*externalapi.DomainTransactionOutput, 900)
|
||||
outputs := make([]*externalapi.DomainTransactionOutput, 1125)
|
||||
for i := 0; i < len(outputs); i++ {
|
||||
outputs[i] = &externalapi.DomainTransactionOutput{
|
||||
ScriptPublicKey: scriptPublicKey,
|
||||
|
||||
@@ -120,14 +120,19 @@ func (v *blockValidator) checkBlockTransactionsFinalized(blockHash *externalapi.
|
||||
return err
|
||||
}
|
||||
|
||||
blockTime := block.Header.TimeInMilliseconds()
|
||||
|
||||
ghostdagData, err := v.ghostdagDataStore.Get(v.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blockTime, err := v.pastMedianTimeManager.PastMedianTime(blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
// If it's not genesis
|
||||
if len(block.Header.ParentHashes()) != 0 {
|
||||
blockTime, err = v.pastMedianTimeManager.PastMedianTime(blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all transactions in the block are finalized.
|
||||
|
||||
@@ -2,6 +2,7 @@ package blockvalidator_test
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
@@ -153,47 +154,18 @@ func TestIsFinalizedTransaction(t *testing.T) {
|
||||
}
|
||||
defer teardown(false)
|
||||
|
||||
// Build a small DAG
|
||||
outerParents := []*externalapi.DomainHash{params.GenesisHash}
|
||||
for i := 0; i < 5; i++ {
|
||||
var innerParents []*externalapi.DomainHash
|
||||
for i := 0; i < 4; i++ {
|
||||
blockHash, _, err := tc.AddBlock(outerParents, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
innerParents = append(innerParents, blockHash)
|
||||
}
|
||||
outerParents = []*externalapi.DomainHash{}
|
||||
for i := 0; i < 3; i++ {
|
||||
blockHash, _, err := tc.AddBlock(innerParents, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
outerParents = append(outerParents, blockHash)
|
||||
}
|
||||
block1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
|
||||
block, err := tc.BuildBlock(&externalapi.DomainCoinbaseData{&externalapi.ScriptPublicKey{}, nil}, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting block: %+v", err)
|
||||
}
|
||||
_, err = tc.ValidateAndInsertBlock(block)
|
||||
if err != nil {
|
||||
t.Fatalf("Error Inserting block: %+v", err)
|
||||
}
|
||||
blockGhostDAG, err := tc.GHOSTDAGDataStore().Get(tc.DatabaseContext(), consensushashing.BlockHash(block))
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting GhostDAG Data: %+v", err)
|
||||
}
|
||||
blockParents := block.Header.ParentHashes()
|
||||
parentToSpend, err := tc.GetBlock(blockParents[0])
|
||||
block1, err := tc.GetBlock(block1Hash)
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting block1: %+v", err)
|
||||
}
|
||||
|
||||
checkForLockTimeAndSequence := func(lockTime, sequence uint64, shouldPass bool) {
|
||||
tx, err := testutils.CreateTransaction(parentToSpend.Transactions[0])
|
||||
tx, err := testutils.CreateTransaction(block1.Transactions[0])
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating tx: %+v", err)
|
||||
}
|
||||
@@ -201,22 +173,23 @@ func TestIsFinalizedTransaction(t *testing.T) {
|
||||
tx.LockTime = lockTime
|
||||
tx.Inputs[0].Sequence = sequence
|
||||
|
||||
_, _, err = tc.AddBlock(blockParents, nil, []*externalapi.DomainTransaction{tx})
|
||||
_, _, err = tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, []*externalapi.DomainTransaction{tx})
|
||||
if (shouldPass && err != nil) || (!shouldPass && !errors.Is(err, ruleerrors.ErrUnfinalizedTx)) {
|
||||
t.Fatalf("shouldPass: %t Unexpected error: %+v", shouldPass, err)
|
||||
t.Fatalf("Unexpected error: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the same blueScore or higher fails, but lower passes.
|
||||
checkForLockTimeAndSequence(blockGhostDAG.BlueScore()+1, 0, false)
|
||||
checkForLockTimeAndSequence(blockGhostDAG.BlueScore(), 0, false)
|
||||
checkForLockTimeAndSequence(blockGhostDAG.BlueScore()-1, 0, true)
|
||||
// The next block blue score is 2, so we check if we see the expected
|
||||
// behaviour when the lock time blue score is higher, lower or equal
|
||||
// to it.
|
||||
checkForLockTimeAndSequence(3, 0, false)
|
||||
checkForLockTimeAndSequence(2, 0, false)
|
||||
checkForLockTimeAndSequence(1, 0, true)
|
||||
|
||||
pastMedianTime, err := tc.PastMedianTimeManager().PastMedianTime(consensushashing.BlockHash(block))
|
||||
pastMedianTime, err := tc.PastMedianTimeManager().PastMedianTime(model.VirtualBlockHash)
|
||||
if err != nil {
|
||||
t.Fatalf("PastMedianTime: %+v", err)
|
||||
}
|
||||
// Check that the same pastMedianTime or higher fails, but lower passes.
|
||||
checkForLockTimeAndSequence(uint64(pastMedianTime)+1, 0, false)
|
||||
checkForLockTimeAndSequence(uint64(pastMedianTime), 0, false)
|
||||
checkForLockTimeAndSequence(uint64(pastMedianTime)-1, 0, true)
|
||||
|
||||
@@ -33,12 +33,7 @@ func TestChainedTransactions(t *testing.T) {
|
||||
}
|
||||
defer teardown(false)
|
||||
|
||||
fundingBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
|
||||
block1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{fundingBlockHash}, nil, nil)
|
||||
block1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
@@ -148,10 +143,10 @@ var unOrderedParentsBlock = externalapi.DomainBlock{
|
||||
}),
|
||||
},
|
||||
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x09, 0xaf, 0x3b, 0x09, 0xa8, 0x8f, 0xfc, 0x7e,
|
||||
0x7d, 0xc6, 0x06, 0x78, 0x04, 0x2b, 0x1c, 0x8a,
|
||||
0xbe, 0x37, 0x0d, 0x55, 0x41, 0xb0, 0xb8, 0x15,
|
||||
0xb1, 0x08, 0xd4, 0x01, 0x2a, 0xf0, 0xfd, 0x29,
|
||||
0x33, 0x77, 0x88, 0xd7, 0x8a, 0xd7, 0x49, 0xbf,
|
||||
0xce, 0x97, 0x58, 0x4f, 0x05, 0x4c, 0xbb, 0x18,
|
||||
0xb4, 0xe4, 0x73, 0x6e, 0x1f, 0xcd, 0x57, 0x5d,
|
||||
0x6b, 0xe4, 0xb1, 0x01, 0xea, 0x7f, 0x01, 0xd7,
|
||||
}),
|
||||
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x80, 0xf7, 0x00, 0xe3, 0x16, 0x3d, 0x04, 0x95,
|
||||
@@ -197,6 +192,12 @@ var unOrderedParentsBlock = externalapi.DomainBlock{
|
||||
LockTime: 0,
|
||||
SubnetworkID: subnetworks.SubnetworkIDCoinbase,
|
||||
Payload: []byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x2e, 0xb5, 0xe8, 0x1c, 0xe2, 0xa7, 0x67, 0x84,
|
||||
0xd1, 0x1a, 0x42, 0x66, 0xcf, 0x12, 0x7f, 0x10,
|
||||
0x9b, 0x6f, 0x84, 0x63, 0xf5, 0x65, 0x5a, 0x65,
|
||||
0xec, 0xed, 0x60, 0xc6, 0x32, 0x7a, 0x9d, 0x08,
|
||||
}),
|
||||
},
|
||||
{
|
||||
Version: 0,
|
||||
@@ -416,10 +417,10 @@ var exampleValidBlock = externalapi.DomainBlock{
|
||||
}),
|
||||
},
|
||||
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x6e, 0xa3, 0x1a, 0xd6, 0xb8, 0xd9, 0xc1, 0xb2,
|
||||
0xab, 0x18, 0xcc, 0x59, 0x6d, 0x03, 0x6b, 0x8d,
|
||||
0x86, 0x59, 0x8f, 0x0e, 0x42, 0x07, 0x81, 0xa9,
|
||||
0x59, 0x16, 0x95, 0x97, 0x8c, 0x9b, 0x0a, 0x19,
|
||||
0x8f, 0x2e, 0x67, 0x13, 0x86, 0xf9, 0x4c, 0x2a,
|
||||
0x1d, 0x1a, 0xc1, 0xf0, 0x30, 0x88, 0xfd, 0x48,
|
||||
0x20, 0xf3, 0x50, 0xd1, 0xfb, 0x6d, 0x06, 0x39,
|
||||
0x72, 0xaa, 0x6f, 0x78, 0x22, 0x64, 0x83, 0x19,
|
||||
}),
|
||||
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x8a, 0xb7, 0xd6, 0x73, 0x1b, 0xe6, 0xc5, 0xd3,
|
||||
@@ -463,6 +464,12 @@ var exampleValidBlock = externalapi.DomainBlock{
|
||||
LockTime: 0,
|
||||
SubnetworkID: subnetworks.SubnetworkIDCoinbase,
|
||||
Payload: []byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x2e, 0xb5, 0xe8, 0x1c, 0xe2, 0xa7, 0x67, 0x84,
|
||||
0xd1, 0x1a, 0x42, 0x66, 0xcf, 0x12, 0x7f, 0x10,
|
||||
0x9b, 0x6f, 0x84, 0x63, 0xf5, 0x65, 0x5a, 0x65,
|
||||
0xec, 0xed, 0x60, 0xc6, 0x32, 0x7a, 0x9d, 0x08,
|
||||
}),
|
||||
},
|
||||
{
|
||||
Version: 0,
|
||||
@@ -712,10 +719,10 @@ var blockWithWrongTxOrder = externalapi.DomainBlock{
|
||||
}),
|
||||
},
|
||||
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0xfc, 0x03, 0xa8, 0x09, 0x03, 0xf6, 0x64, 0xd9,
|
||||
0xba, 0xab, 0x6d, 0x50, 0x1c, 0x67, 0xcb, 0xff,
|
||||
0x2e, 0x53, 0x76, 0x6b, 0x02, 0xa9, 0xd4, 0x78,
|
||||
0x2b, 0x49, 0xe8, 0x90, 0x33, 0x90, 0xdd, 0xdf,
|
||||
0xaf, 0xba, 0x3c, 0x18, 0x9e, 0x44, 0xac, 0x7c,
|
||||
0xb7, 0xcc, 0x90, 0x0b, 0x75, 0x88, 0x6b, 0x9c,
|
||||
0x3e, 0xc9, 0xea, 0xf1, 0x5c, 0xaf, 0x28, 0x30,
|
||||
0x34, 0x23, 0xf5, 0xeb, 0x18, 0xdf, 0xd1, 0x75,
|
||||
}),
|
||||
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0xa0, 0x69, 0x2d, 0x16, 0xb5, 0xd7, 0xe4, 0xf3,
|
||||
@@ -764,6 +771,12 @@ var blockWithWrongTxOrder = externalapi.DomainBlock{
|
||||
LockTime: 0,
|
||||
SubnetworkID: subnetworks.SubnetworkIDCoinbase,
|
||||
Payload: []byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||
0x2e, 0xb5, 0xe8, 0x1c, 0xe2, 0xa7, 0x67, 0x84,
|
||||
0xd1, 0x1a, 0x42, 0x66, 0xcf, 0x12, 0x7f, 0x10,
|
||||
0x9b, 0x6f, 0x84, 0x63, 0xf5, 0x65, 0x5a, 0x65,
|
||||
0xec, 0xed, 0x60, 0xc6, 0x32, 0x7a, 0x9d, 0x08,
|
||||
}),
|
||||
},
|
||||
|
||||
{
|
||||
@@ -866,6 +879,7 @@ var blockWithWrongTxOrder = externalapi.DomainBlock{
|
||||
LockTime: 0,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{11},
|
||||
Payload: []byte{},
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0xFF, 0xFF}),
|
||||
},
|
||||
{
|
||||
Version: 0,
|
||||
@@ -1077,6 +1091,10 @@ func initBlockWithInvalidBlockSize(params *dagconfig.Params, tc testapi.TestCons
|
||||
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
|
||||
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
|
||||
&externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}},
|
||||
PayloadHash: *externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
Payload: []byte{0x01},
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,11 @@ func (v *blockValidator) ValidateHeaderInContext(blockHash *externalapi.DomainHa
|
||||
}
|
||||
|
||||
if !hasValidatedHeader {
|
||||
err = v.ghostdagManager.GHOSTDAG(blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var logErr error
|
||||
log.Debug(logger.NewLogClosure(func() string {
|
||||
var ghostdagData *model.BlockGHOSTDAGData
|
||||
|
||||
@@ -54,16 +54,10 @@ func (v *blockValidator) ValidatePruningPointViolationAndProofOfWorkAndDifficult
|
||||
}
|
||||
|
||||
func (v *blockValidator) validateDifficulty(blockHash *externalapi.DomainHash) error {
|
||||
// We need to calculate GHOSTDAG for the block in order to check its difficulty
|
||||
err := v.ghostdagManager.GHOSTDAG(blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure the difficulty specified in the block header matches
|
||||
// the calculated difficulty based on the previous block and
|
||||
// difficulty retarget rules.
|
||||
expectedBits, err := v.difficultyManager.StageDAADataAndReturnRequiredDifficulty(blockHash)
|
||||
expectedBits, err := v.difficultyManager.RequiredDifficulty(blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -246,19 +246,16 @@ func TestCheckPruningPointViolation(t *testing.T) {
|
||||
// TestValidateDifficulty verifies that in case of a block with an unexpected difficulty,
|
||||
// an appropriate error message (ErrUnexpectedDifficulty) will be returned on the
|
||||
// function ValidatePruningPointViolationAndProofOfWorkAndDifficulty. The required difficulty is
|
||||
// "calculated" by the mocDifficultyManager, where mocDifficultyManager is special implementation
|
||||
// of the type DifficultyManager for this test (defined below).
|
||||
// "calculated" by the function (dm *mocDifficultyManager) RequiredDifficulty ,
|
||||
// where mocDifficultyManager is special implementation of the type DifficultyManager for this test (defined below).
|
||||
func TestValidateDifficulty(t *testing.T) {
|
||||
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
|
||||
|
||||
factory := consensus.NewFactory()
|
||||
mocDifficulty := &mocDifficultyManager{}
|
||||
factory.SetTestDifficultyManager(func(_ model.DBReader, _ model.GHOSTDAGManager, _ model.GHOSTDAGDataStore,
|
||||
_ model.BlockHeaderStore, daaBlocksStore model.DAABlocksStore, _ model.DAGTopologyManager,
|
||||
_ model.DAGTraversalManager, _ *big.Int, _ int, _ bool, _ time.Duration,
|
||||
_ *externalapi.DomainHash) model.DifficultyManager {
|
||||
|
||||
mocDifficulty.daaBlocksStore = daaBlocksStore
|
||||
factory.SetTestDifficultyManager(func(model.DBReader, model.GHOSTDAGManager, model.GHOSTDAGDataStore,
|
||||
model.BlockHeaderStore, model.DAGTopologyManager, model.DAGTraversalManager, *big.Int, int, bool, time.Duration,
|
||||
*externalapi.DomainHash) model.DifficultyManager {
|
||||
return mocDifficulty
|
||||
})
|
||||
genesisDifficulty := params.GenesisBlock.Header.Bits()
|
||||
@@ -296,19 +293,9 @@ func TestValidateDifficulty(t *testing.T) {
|
||||
type mocDifficultyManager struct {
|
||||
testDifficulty uint32
|
||||
testGenesisBits uint32
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
}
|
||||
|
||||
// RequiredDifficulty returns the difficulty required for the test
|
||||
func (dm *mocDifficultyManager) RequiredDifficulty(*externalapi.DomainHash) (uint32, error) {
|
||||
return dm.testDifficulty, nil
|
||||
}
|
||||
|
||||
// StageDAADataAndReturnRequiredDifficulty returns the difficulty required for the test
|
||||
func (dm *mocDifficultyManager) StageDAADataAndReturnRequiredDifficulty(blockHash *externalapi.DomainHash) (uint32, error) {
|
||||
// Populate daaBlocksStore with fake values
|
||||
dm.daaBlocksStore.StageDAAScore(blockHash, 0)
|
||||
dm.daaBlocksStore.StageBlockDAAAddedBlocks(blockHash, nil)
|
||||
|
||||
return dm.testDifficulty, nil
|
||||
}
|
||||
|
||||
@@ -4,9 +4,8 @@ import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashset"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type coinbaseManager struct {
|
||||
@@ -17,7 +16,6 @@ type coinbaseManager struct {
|
||||
databaseContext model.DBReader
|
||||
ghostdagDataStore model.GHOSTDAGDataStore
|
||||
acceptanceDataStore model.AcceptanceDataStore
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
}
|
||||
|
||||
func (c *coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.DomainHash,
|
||||
@@ -33,14 +31,9 @@ func (c *coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.Dom
|
||||
return nil, err
|
||||
}
|
||||
|
||||
daaAddedBlocksSet, err := c.daaAddedBlocksSet(blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txOuts := make([]*externalapi.DomainTransactionOutput, 0, len(ghostdagData.MergeSetBlues()))
|
||||
for i, blue := range ghostdagData.MergeSetBlues() {
|
||||
txOut, hasReward, err := c.coinbaseOutputForBlueBlock(blue, acceptanceData[i], daaAddedBlocksSet)
|
||||
txOut, hasReward, err := c.coinbaseOutputForBlueBlock(blue, acceptanceData[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,20 +43,13 @@ func (c *coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.Dom
|
||||
}
|
||||
}
|
||||
|
||||
txOut, hasReward, err := c.coinbaseOutputForRewardFromRedBlocks(ghostdagData, acceptanceData, daaAddedBlocksSet, coinbaseData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if hasReward {
|
||||
txOuts = append(txOuts, txOut)
|
||||
}
|
||||
|
||||
payload, err := c.serializeCoinbasePayload(ghostdagData.BlueScore(), coinbaseData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payloadHash := hashes.PayloadHash(payload)
|
||||
|
||||
return &externalapi.DomainTransaction{
|
||||
Version: constants.MaxTransactionVersion,
|
||||
Inputs: []*externalapi.DomainTransactionInput{},
|
||||
@@ -71,30 +57,30 @@ func (c *coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.Dom
|
||||
LockTime: 0,
|
||||
SubnetworkID: subnetworks.SubnetworkIDCoinbase,
|
||||
Gas: 0,
|
||||
PayloadHash: *payloadHash,
|
||||
Payload: payload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *coinbaseManager) daaAddedBlocksSet(blockHash *externalapi.DomainHash) (hashset.HashSet, error) {
|
||||
daaAddedBlocks, err := c.daaBlocksStore.DAAAddedBlocks(c.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hashset.NewFromSlice(daaAddedBlocks...), nil
|
||||
}
|
||||
|
||||
// coinbaseOutputForBlueBlock calculates the output that should go into the coinbase transaction of blueBlock
|
||||
// If blueBlock gets no fee - returns nil for txOut
|
||||
func (c *coinbaseManager) coinbaseOutputForBlueBlock(blueBlock *externalapi.DomainHash,
|
||||
blockAcceptanceData *externalapi.BlockAcceptanceData,
|
||||
mergingBlockDAAAddedBlocksSet hashset.HashSet) (*externalapi.DomainTransactionOutput, bool, error) {
|
||||
blockAcceptanceData *externalapi.BlockAcceptanceData) (*externalapi.DomainTransactionOutput, bool, error) {
|
||||
|
||||
totalReward, err := c.calcMergedBlockReward(blueBlock, blockAcceptanceData, mergingBlockDAAAddedBlocksSet)
|
||||
totalFees := uint64(0)
|
||||
for _, txAcceptanceData := range blockAcceptanceData.TransactionAcceptanceData {
|
||||
if txAcceptanceData.IsAccepted {
|
||||
totalFees += txAcceptanceData.Fee
|
||||
}
|
||||
}
|
||||
|
||||
subsidy, err := c.calcBlockSubsidy(blueBlock)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
totalReward := subsidy + totalFees
|
||||
|
||||
if totalReward == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
@@ -113,31 +99,6 @@ func (c *coinbaseManager) coinbaseOutputForBlueBlock(blueBlock *externalapi.Doma
|
||||
return txOut, true, nil
|
||||
}
|
||||
|
||||
func (c *coinbaseManager) coinbaseOutputForRewardFromRedBlocks(ghostdagData *model.BlockGHOSTDAGData,
|
||||
acceptanceData externalapi.AcceptanceData, daaAddedBlocksSet hashset.HashSet,
|
||||
coinbaseData *externalapi.DomainCoinbaseData) (*externalapi.DomainTransactionOutput, bool, error) {
|
||||
|
||||
totalReward := uint64(0)
|
||||
mergeSetBluesCount := len(ghostdagData.MergeSetBlues())
|
||||
for i, red := range ghostdagData.MergeSetReds() {
|
||||
reward, err := c.calcMergedBlockReward(red, acceptanceData[mergeSetBluesCount+i], daaAddedBlocksSet)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
totalReward += reward
|
||||
}
|
||||
|
||||
if totalReward == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
return &externalapi.DomainTransactionOutput{
|
||||
Value: totalReward,
|
||||
ScriptPublicKey: coinbaseData.ScriptPublicKey,
|
||||
}, true, nil
|
||||
}
|
||||
|
||||
// calcBlockSubsidy returns the subsidy amount a block at the provided blue score
|
||||
// should have. This is mainly used for determining how much the coinbase for
|
||||
// newly generated blocks awards as well as validating the coinbase for blocks
|
||||
@@ -153,40 +114,13 @@ func (c *coinbaseManager) calcBlockSubsidy(blockHash *externalapi.DomainHash) (u
|
||||
return c.baseSubsidy, nil
|
||||
}
|
||||
|
||||
daaScore, err := c.daaBlocksStore.DAAScore(c.databaseContext, blockHash)
|
||||
ghostdagData, err := c.ghostdagDataStore.Get(c.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Equivalent to: baseSubsidy / 2^(daaScore/subsidyHalvingInterval)
|
||||
return c.baseSubsidy >> uint(daaScore/c.subsidyReductionInterval), nil
|
||||
}
|
||||
|
||||
func (c *coinbaseManager) calcMergedBlockReward(blockHash *externalapi.DomainHash,
|
||||
blockAcceptanceData *externalapi.BlockAcceptanceData, mergingBlockDAAAddedBlocksSet hashset.HashSet) (uint64, error) {
|
||||
|
||||
if !blockHash.Equal(blockAcceptanceData.BlockHash) {
|
||||
return 0, errors.Errorf("blockAcceptanceData.BlockHash is expected to be %s but got %s",
|
||||
blockHash, blockAcceptanceData.BlockHash)
|
||||
}
|
||||
|
||||
if !mergingBlockDAAAddedBlocksSet.Contains(blockHash) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
totalFees := uint64(0)
|
||||
for _, txAcceptanceData := range blockAcceptanceData.TransactionAcceptanceData {
|
||||
if txAcceptanceData.IsAccepted {
|
||||
totalFees += txAcceptanceData.Fee
|
||||
}
|
||||
}
|
||||
|
||||
subsidy, err := c.calcBlockSubsidy(blockHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return subsidy + totalFees, nil
|
||||
// Equivalent to: baseSubsidy / 2^(blueScore/subsidyHalvingInterval)
|
||||
return c.baseSubsidy >> uint(ghostdagData.BlueScore()/c.subsidyReductionInterval), nil
|
||||
}
|
||||
|
||||
// New instantiates a new CoinbaseManager
|
||||
@@ -198,8 +132,7 @@ func New(
|
||||
coinbasePayloadScriptPublicKeyMaxLength uint8,
|
||||
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
acceptanceDataStore model.AcceptanceDataStore,
|
||||
daaBlocksStore model.DAABlocksStore) model.CoinbaseManager {
|
||||
acceptanceDataStore model.AcceptanceDataStore) model.CoinbaseManager {
|
||||
|
||||
return &coinbaseManager{
|
||||
databaseContext: databaseContext,
|
||||
@@ -210,6 +143,5 @@ func New(
|
||||
|
||||
ghostdagDataStore: ghostdagDataStore,
|
||||
acceptanceDataStore: acceptanceDataStore,
|
||||
daaBlocksStore: daaBlocksStore,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,32 +21,17 @@ func TestVirtualDiff(t *testing.T) {
|
||||
defer teardown(false)
|
||||
|
||||
// Add block A over the genesis
|
||||
blockAHash, blockInsertionResult, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
|
||||
blockHash, blockInsertionResult, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error adding block A: %+v", err)
|
||||
}
|
||||
|
||||
virtualUTXODiff := blockInsertionResult.VirtualUTXODiff
|
||||
if virtualUTXODiff.ToRemove().Len() != 0 {
|
||||
t.Fatalf("Unexpected length %d for virtualUTXODiff.ToRemove()", virtualUTXODiff.ToRemove().Len())
|
||||
}
|
||||
|
||||
// Because the genesis is not in block A's DAA window, block A's coinbase doesn't pay to it, so it has no outputs.
|
||||
if virtualUTXODiff.ToAdd().Len() != 0 {
|
||||
t.Fatalf("Unexpected length %d for virtualUTXODiff.ToAdd()", virtualUTXODiff.ToAdd().Len())
|
||||
}
|
||||
|
||||
blockBHash, blockInsertionResult, err := tc.AddBlock([]*externalapi.DomainHash{blockAHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error adding block A: %+v", err)
|
||||
}
|
||||
|
||||
blockB, err := tc.BlockStore().Block(tc.DatabaseContext(), blockBHash)
|
||||
block, err := tc.BlockStore().Block(tc.DatabaseContext(), blockHash)
|
||||
if err != nil {
|
||||
t.Fatalf("Block: %+v", err)
|
||||
}
|
||||
|
||||
virtualUTXODiff = blockInsertionResult.VirtualUTXODiff
|
||||
virtualUTXODiff := blockInsertionResult.VirtualUTXODiff
|
||||
if virtualUTXODiff.ToRemove().Len() != 0 {
|
||||
t.Fatalf("Unexpected length %d for virtualUTXODiff.ToRemove()", virtualUTXODiff.ToRemove().Len())
|
||||
}
|
||||
@@ -64,17 +49,17 @@ func TestVirtualDiff(t *testing.T) {
|
||||
}
|
||||
|
||||
if !outpoint.Equal(&externalapi.DomainOutpoint{
|
||||
TransactionID: *consensushashing.TransactionID(blockB.Transactions[0]),
|
||||
TransactionID: *consensushashing.TransactionID(block.Transactions[0]),
|
||||
Index: 0,
|
||||
}) {
|
||||
t.Fatalf("Unexpected outpoint %s", outpoint)
|
||||
}
|
||||
|
||||
if !entry.Equal(utxo.NewUTXOEntry(
|
||||
blockB.Transactions[0].Outputs[0].Value,
|
||||
blockB.Transactions[0].Outputs[0].ScriptPublicKey,
|
||||
block.Transactions[0].Outputs[0].Value,
|
||||
block.Transactions[0].Outputs[0].ScriptPublicKey,
|
||||
true,
|
||||
2, //Expected virtual DAA score
|
||||
2, //Expected virtual blue score
|
||||
)) {
|
||||
t.Fatalf("Unexpected entry %s", entry)
|
||||
}
|
||||
|
||||
@@ -38,24 +38,18 @@ func (csm *consensusStateManager) CalculatePastUTXOAndAcceptanceData(blockHash *
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
daaScore, err := csm.daaBlocksStore.DAAScore(csm.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
log.Debugf("Restored the past UTXO of block %s with selectedParent %s. "+
|
||||
"Diff toAdd length: %d, toRemove length: %d", blockHash, blockGHOSTDAGData.SelectedParent(),
|
||||
selectedParentPastUTXO.ToAdd().Len(), selectedParentPastUTXO.ToRemove().Len())
|
||||
|
||||
log.Debugf("Applying blue blocks to the selected parent past UTXO of block %s", blockHash)
|
||||
acceptanceData, utxoDiff, err := csm.applyMergeSetBlocks(blockHash, selectedParentPastUTXO, blockGHOSTDAGData, daaScore)
|
||||
acceptanceData, utxoDiff, err := csm.applyMergeSetBlocks(blockHash, selectedParentPastUTXO, blockGHOSTDAGData)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
log.Debugf("Calculating the multiset of %s", blockHash)
|
||||
multiset, err := csm.calculateMultiset(acceptanceData, blockGHOSTDAGData, daaScore)
|
||||
multiset, err := csm.calculateMultiset(acceptanceData, blockGHOSTDAGData)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@@ -121,7 +115,7 @@ func (csm *consensusStateManager) restorePastUTXO(blockHash *externalapi.DomainH
|
||||
}
|
||||
|
||||
func (csm *consensusStateManager) applyMergeSetBlocks(blockHash *externalapi.DomainHash,
|
||||
selectedParentPastUTXODiff externalapi.MutableUTXODiff, ghostdagData *model.BlockGHOSTDAGData, daaScore uint64) (
|
||||
selectedParentPastUTXODiff externalapi.MutableUTXODiff, ghostdagData *model.BlockGHOSTDAGData) (
|
||||
externalapi.AcceptanceData, externalapi.MutableUTXODiff, error) {
|
||||
|
||||
log.Debugf("applyMergeSetBlocks start for block %s", blockHash)
|
||||
@@ -162,7 +156,7 @@ func (csm *consensusStateManager) applyMergeSetBlocks(blockHash *externalapi.Dom
|
||||
transactionID, mergeSetBlockHash)
|
||||
|
||||
isAccepted, accumulatedMass, err = csm.maybeAcceptTransaction(transaction, blockHash, isSelectedParent,
|
||||
accumulatedUTXODiff, accumulatedMass, selectedParentMedianTime, daaScore)
|
||||
accumulatedUTXODiff, accumulatedMass, selectedParentMedianTime, ghostdagData.BlueScore())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -192,7 +186,7 @@ func (csm *consensusStateManager) applyMergeSetBlocks(blockHash *externalapi.Dom
|
||||
|
||||
func (csm *consensusStateManager) maybeAcceptTransaction(transaction *externalapi.DomainTransaction,
|
||||
blockHash *externalapi.DomainHash, isSelectedParent bool, accumulatedUTXODiff externalapi.MutableUTXODiff,
|
||||
accumulatedMassBefore uint64, selectedParentPastMedianTime int64, blockDAAScore uint64) (
|
||||
accumulatedMassBefore uint64, selectedParentPastMedianTime int64, blockBlueScore uint64) (
|
||||
isAccepted bool, accumulatedMassAfter uint64, err error) {
|
||||
|
||||
transactionID := consensushashing.TransactionID(transaction)
|
||||
@@ -243,7 +237,7 @@ func (csm *consensusStateManager) maybeAcceptTransaction(transaction *externalap
|
||||
}
|
||||
|
||||
log.Tracef("Adding transaction %s in block %s to the accumulated diff", transactionID, blockHash)
|
||||
err = accumulatedUTXODiff.AddTransaction(transaction, blockDAAScore)
|
||||
err = accumulatedUTXODiff.AddTransaction(transaction, blockBlueScore)
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ type consensusStateManager struct {
|
||||
coinbaseManager model.CoinbaseManager
|
||||
mergeDepthManager model.MergeDepthManager
|
||||
finalityManager model.FinalityManager
|
||||
difficultyManager model.DifficultyManager
|
||||
|
||||
headersSelectedTipStore model.HeaderSelectedTipStore
|
||||
blockStatusStore model.BlockStatusStore
|
||||
@@ -37,7 +36,6 @@ type consensusStateManager struct {
|
||||
acceptanceDataStore model.AcceptanceDataStore
|
||||
blockHeaderStore model.BlockHeaderStore
|
||||
pruningStore model.PruningStore
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
|
||||
stores []model.Store
|
||||
}
|
||||
@@ -61,7 +59,6 @@ func New(
|
||||
coinbaseManager model.CoinbaseManager,
|
||||
mergeDepthManager model.MergeDepthManager,
|
||||
finalityManager model.FinalityManager,
|
||||
difficultyManager model.DifficultyManager,
|
||||
|
||||
blockStatusStore model.BlockStatusStore,
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
@@ -73,8 +70,7 @@ func New(
|
||||
acceptanceDataStore model.AcceptanceDataStore,
|
||||
blockHeaderStore model.BlockHeaderStore,
|
||||
headersSelectedTipStore model.HeaderSelectedTipStore,
|
||||
pruningStore model.PruningStore,
|
||||
daaBlocksStore model.DAABlocksStore) (model.ConsensusStateManager, error) {
|
||||
pruningStore model.PruningStore) (model.ConsensusStateManager, error) {
|
||||
|
||||
csm := &consensusStateManager{
|
||||
pruningDepth: pruningDepth,
|
||||
@@ -94,7 +90,6 @@ func New(
|
||||
coinbaseManager: coinbaseManager,
|
||||
mergeDepthManager: mergeDepthManager,
|
||||
finalityManager: finalityManager,
|
||||
difficultyManager: difficultyManager,
|
||||
|
||||
multisetStore: multisetStore,
|
||||
blockStore: blockStore,
|
||||
@@ -107,7 +102,6 @@ func New(
|
||||
blockHeaderStore: blockHeaderStore,
|
||||
headersSelectedTipStore: headersSelectedTipStore,
|
||||
pruningStore: pruningStore,
|
||||
daaBlocksStore: daaBlocksStore,
|
||||
|
||||
stores: []model.Store{
|
||||
consensusStateStore,
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func (csm *consensusStateManager) calculateMultiset(
|
||||
acceptanceData externalapi.AcceptanceData, blockGHOSTDAGData *model.BlockGHOSTDAGData, daaScore uint64) (model.Multiset, error) {
|
||||
acceptanceData externalapi.AcceptanceData, blockGHOSTDAGData *model.BlockGHOSTDAGData) (model.Multiset, error) {
|
||||
|
||||
log.Debugf("calculateMultiset start for block with selected parent %s", blockGHOSTDAGData.SelectedParent())
|
||||
defer log.Debugf("calculateMultiset end for block with selected parent %s", blockGHOSTDAGData.SelectedParent())
|
||||
@@ -38,7 +38,7 @@ func (csm *consensusStateManager) calculateMultiset(
|
||||
isCoinbase := i == 0
|
||||
log.Tracef("Is transaction %s a coinbase transaction: %t", transactionID, isCoinbase)
|
||||
|
||||
err := addTransactionToMultiset(ms, transaction, daaScore, isCoinbase)
|
||||
err := addTransactionToMultiset(ms, transaction, blockGHOSTDAGData.BlueScore(), isCoinbase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (csm *consensusStateManager) calculateMultiset(
|
||||
}
|
||||
|
||||
func addTransactionToMultiset(multiset model.Multiset, transaction *externalapi.DomainTransaction,
|
||||
blockDAAScore uint64, isCoinbase bool) error {
|
||||
blockBlueScore uint64, isCoinbase bool) error {
|
||||
|
||||
transactionID := consensushashing.TransactionID(transaction)
|
||||
log.Tracef("addTransactionToMultiset start for transaction %s", transactionID)
|
||||
@@ -70,7 +70,7 @@ func addTransactionToMultiset(multiset model.Multiset, transaction *externalapi.
|
||||
TransactionID: *transactionID,
|
||||
Index: uint32(i),
|
||||
}
|
||||
utxoEntry := utxo.NewUTXOEntry(output.Value, output.ScriptPublicKey, isCoinbase, blockDAAScore)
|
||||
utxoEntry := utxo.NewUTXOEntry(output.Value, output.ScriptPublicKey, isCoinbase, blockBlueScore)
|
||||
|
||||
log.Tracef("Adding input %s at index %d from the multiset", transactionID, i)
|
||||
err := addUTXOToMultiset(multiset, utxoEntry, outpoint)
|
||||
|
||||
@@ -261,12 +261,7 @@ func TestTransactionAcceptance(t *testing.T) {
|
||||
t.Fatalf("Error creating tip: %+v", err)
|
||||
}
|
||||
|
||||
finalTipScriptPublicKey := &externalapi.ScriptPublicKey{Script: []byte{4}, Version: 0}
|
||||
finalTipHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{finalTipSelectedParentHash, redHash, blueHash},
|
||||
&externalapi.DomainCoinbaseData{
|
||||
ScriptPublicKey: finalTipScriptPublicKey,
|
||||
ExtraData: nil,
|
||||
},
|
||||
finalTipHash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{finalTipSelectedParentHash, redHash, blueHash}, nil,
|
||||
nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating finalTip: %+v", err)
|
||||
@@ -359,7 +354,7 @@ func TestTransactionAcceptance(t *testing.T) {
|
||||
}
|
||||
|
||||
// We expect the coinbase transaction to pay reward for the selected parent, the
|
||||
// blue block, and bestow the red block reward to the merging block.
|
||||
// blue block, and not for the red block.
|
||||
expectedCoinbase := &externalapi.DomainTransaction{
|
||||
Version: constants.MaxTransactionVersion,
|
||||
Inputs: nil,
|
||||
@@ -372,14 +367,11 @@ func TestTransactionAcceptance(t *testing.T) {
|
||||
Value: 50*constants.SompiPerKaspa + 1, // testutils.CreateTransaction pays a fee of 1 sompi
|
||||
ScriptPublicKey: blueScriptPublicKey,
|
||||
},
|
||||
{
|
||||
Value: 50*constants.SompiPerKaspa + 1,
|
||||
ScriptPublicKey: finalTipScriptPublicKey,
|
||||
},
|
||||
},
|
||||
LockTime: 0,
|
||||
SubnetworkID: subnetworks.SubnetworkIDCoinbase,
|
||||
Gas: 0,
|
||||
PayloadHash: finalTip.Transactions[0].PayloadHash,
|
||||
Payload: finalTip.Transactions[0].Payload,
|
||||
}
|
||||
if !finalTip.Transactions[transactionhelper.CoinbaseTransactionIndex].Equal(expectedCoinbase) {
|
||||
|
||||
@@ -42,12 +42,6 @@ func (csm *consensusStateManager) updateVirtual(newBlockHash *externalapi.Domain
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// This is needed for `csm.CalculatePastUTXOAndAcceptanceData`
|
||||
_, err = csm.difficultyManager.StageDAADataAndReturnRequiredDifficulty(model.VirtualBlockHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
log.Debugf("Calculating past UTXO, acceptance data, and multiset for the new virtual block")
|
||||
virtualUTXODiff, virtualAcceptanceData, virtualMultiset, err := csm.CalculatePastUTXOAndAcceptanceData(model.VirtualBlockHash)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,7 +16,6 @@ type dagTraversalManager struct {
|
||||
ghostdagDataStore model.GHOSTDAGDataStore
|
||||
reachabilityDataStore model.ReachabilityDataStore
|
||||
consensusStateStore model.ConsensusStateStore
|
||||
genesisHash *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// New instantiates a new DAGTraversalManager
|
||||
@@ -26,8 +25,7 @@ func New(
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
reachabilityDataStore model.ReachabilityDataStore,
|
||||
ghostdagManager model.GHOSTDAGManager,
|
||||
conssensusStateStore model.ConsensusStateStore,
|
||||
genesisHash *externalapi.DomainHash) model.DAGTraversalManager {
|
||||
conssensusStateStore model.ConsensusStateStore) model.DAGTraversalManager {
|
||||
return &dagTraversalManager{
|
||||
databaseContext: databaseContext,
|
||||
dagTopologyManager: dagTopologyManager,
|
||||
@@ -35,7 +33,6 @@ func New(
|
||||
reachabilityDataStore: reachabilityDataStore,
|
||||
ghostdagManager: ghostdagManager,
|
||||
consensusStateStore: conssensusStateStore,
|
||||
genesisHash: genesisHash,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,15 @@ import (
|
||||
// If the number of blocks in the past of startingNode is less then windowSize,
|
||||
// the window will be padded by genesis blocks to achieve a size of windowSize.
|
||||
func (dtm *dagTraversalManager) BlockWindow(startingBlock *externalapi.DomainHash, windowSize int) ([]*externalapi.DomainHash, error) {
|
||||
currentGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, startingBlock)
|
||||
currentHash := startingBlock
|
||||
currentGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
windowHeap := dtm.newSizedUpHeap(windowSize)
|
||||
|
||||
for windowHeap.len() <= windowSize && currentGHOSTDAGData.SelectedParent() != nil && !currentGHOSTDAGData.SelectedParent().Equal(dtm.genesisHash) {
|
||||
for windowHeap.len() <= windowSize && currentGHOSTDAGData.SelectedParent() != nil {
|
||||
selectedParentGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentGHOSTDAGData.SelectedParent())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -57,12 +58,21 @@ func (dtm *dagTraversalManager) BlockWindow(startingBlock *externalapi.DomainHas
|
||||
break
|
||||
}
|
||||
}
|
||||
currentHash = currentGHOSTDAGData.SelectedParent()
|
||||
currentGHOSTDAGData = selectedParentGHOSTDAGData
|
||||
}
|
||||
|
||||
window := make([]*externalapi.DomainHash, 0, len(windowHeap.impl.slice))
|
||||
window := make([]*externalapi.DomainHash, 0, windowSize)
|
||||
for _, b := range windowHeap.impl.slice {
|
||||
window = append(window, b.hash)
|
||||
}
|
||||
|
||||
if len(window) < windowSize {
|
||||
genesis := currentHash
|
||||
for len(window) < windowSize {
|
||||
window = append(window, genesis)
|
||||
}
|
||||
}
|
||||
|
||||
return window, nil
|
||||
}
|
||||
|
||||
@@ -15,296 +15,296 @@ import (
|
||||
|
||||
func TestBlockWindow(t *testing.T) {
|
||||
tests := map[string][]*struct {
|
||||
parents []string
|
||||
id string //id is a virtual entity that is used only for tests so we can define relations between blocks without knowing their hash
|
||||
expectedWindow []string
|
||||
parents []string
|
||||
id string //id is a virtual entity that is used only for tests so we can define relations between blocks without knowing their hash
|
||||
expectedWindowWithGenesisPadding []string
|
||||
}{
|
||||
dagconfig.MainnetParams.Name: {
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"C", "D"},
|
||||
id: "E",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"C", "D"},
|
||||
id: "E",
|
||||
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"C", "D"},
|
||||
id: "F",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"C", "D"},
|
||||
id: "F",
|
||||
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindow: []string{"G"},
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindowWithGenesisPadding: []string{"G", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindow: []string{"F", "D", "H", "C", "B", "G"},
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindowWithGenesisPadding: []string{"F", "C", "D", "H", "G", "B", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindow: []string{"I", "F", "D", "H", "C", "B", "G"},
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindowWithGenesisPadding: []string{"I", "F", "C", "D", "H", "G", "B", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindow: []string{"J", "I", "F", "D", "H", "C", "B", "G"},
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindowWithGenesisPadding: []string{"J", "I", "F", "C", "D", "H", "G", "B", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindow: []string{"K", "J", "I", "F", "D", "H", "C", "B", "G"},
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindowWithGenesisPadding: []string{"K", "J", "I", "F", "C", "D", "H", "G", "B", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "H", "C", "B", "G"},
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindowWithGenesisPadding: []string{"L", "K", "J", "I", "F", "C", "D", "H", "G", "B"},
|
||||
},
|
||||
{
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "B"},
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindowWithGenesisPadding: []string{"M", "L", "K", "J", "I", "F", "C", "D", "H", "G"},
|
||||
},
|
||||
{
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "C", "D", "H"},
|
||||
},
|
||||
},
|
||||
dagconfig.TestnetParams.Name: {
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"C", "D"},
|
||||
id: "E",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"C", "D"},
|
||||
id: "E",
|
||||
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"C", "D"},
|
||||
id: "F",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"C", "D"},
|
||||
id: "F",
|
||||
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindow: []string{"G"},
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindowWithGenesisPadding: []string{"G", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindow: []string{"F", "D", "H", "C", "G", "B"},
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindowWithGenesisPadding: []string{"F", "C", "H", "D", "G", "B", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindow: []string{"I", "F", "D", "H", "C", "G", "B"},
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindowWithGenesisPadding: []string{"I", "F", "C", "H", "D", "G", "B", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindow: []string{"J", "I", "F", "D", "H", "C", "G", "B"},
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindowWithGenesisPadding: []string{"J", "I", "F", "C", "H", "D", "G", "B", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindow: []string{"K", "J", "I", "F", "D", "H", "C", "G", "B"},
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindowWithGenesisPadding: []string{"K", "J", "I", "F", "C", "H", "D", "G", "B", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "H", "C", "G", "B"},
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindowWithGenesisPadding: []string{"L", "K", "J", "I", "F", "C", "H", "D", "G", "B"},
|
||||
},
|
||||
{
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "G"},
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindowWithGenesisPadding: []string{"M", "L", "K", "J", "I", "F", "C", "H", "D", "G"},
|
||||
},
|
||||
{
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "C", "H", "D"},
|
||||
},
|
||||
},
|
||||
dagconfig.DevnetParams.Name: {
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"C", "D"},
|
||||
id: "E",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"C", "D"},
|
||||
id: "E",
|
||||
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"C", "D"},
|
||||
id: "F",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"C", "D"},
|
||||
id: "F",
|
||||
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindow: []string{"G"},
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindowWithGenesisPadding: []string{"G", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindow: []string{"F", "H", "D", "C", "G", "B"},
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindowWithGenesisPadding: []string{"F", "H", "C", "D", "B", "G", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindow: []string{"I", "F", "H", "D", "C", "G", "B"},
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindowWithGenesisPadding: []string{"I", "F", "H", "C", "D", "B", "G", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindow: []string{"J", "I", "F", "H", "D", "C", "G", "B"},
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindowWithGenesisPadding: []string{"J", "I", "F", "H", "C", "D", "B", "G", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindow: []string{"K", "J", "I", "F", "H", "D", "C", "G", "B"},
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindowWithGenesisPadding: []string{"K", "J", "I", "F", "H", "C", "D", "B", "G", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindow: []string{"L", "K", "J", "I", "F", "H", "D", "C", "G", "B"},
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindowWithGenesisPadding: []string{"L", "K", "J", "I", "F", "H", "C", "D", "B", "G"},
|
||||
},
|
||||
{
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "H", "D", "C", "G"},
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindowWithGenesisPadding: []string{"M", "L", "K", "J", "I", "F", "H", "C", "D", "B"},
|
||||
},
|
||||
{
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "H", "D", "C"},
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "H", "C", "D"},
|
||||
},
|
||||
},
|
||||
dagconfig.SimnetParams.Name: {
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "B",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "C",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindow: []string{"B"},
|
||||
parents: []string{"B"},
|
||||
id: "D",
|
||||
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"D", "C"},
|
||||
id: "E",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"D", "C"},
|
||||
id: "E",
|
||||
expectedWindowWithGenesisPadding: []string{"D", "C", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"D", "C"},
|
||||
id: "F",
|
||||
expectedWindow: []string{"D", "C", "B"},
|
||||
parents: []string{"D", "C"},
|
||||
id: "F",
|
||||
expectedWindowWithGenesisPadding: []string{"D", "C", "B", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindow: []string{},
|
||||
parents: []string{"A"},
|
||||
id: "G",
|
||||
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindow: []string{"G"},
|
||||
parents: []string{"G"},
|
||||
id: "H",
|
||||
expectedWindowWithGenesisPadding: []string{"G", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindow: []string{"F", "H", "D", "C", "B", "G"},
|
||||
parents: []string{"H", "F"},
|
||||
id: "I",
|
||||
expectedWindowWithGenesisPadding: []string{"F", "D", "H", "C", "B", "G", "A", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindow: []string{"I", "F", "H", "D", "C", "B", "G"},
|
||||
parents: []string{"I"},
|
||||
id: "J",
|
||||
expectedWindowWithGenesisPadding: []string{"I", "F", "D", "H", "C", "B", "G", "A", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindow: []string{"J", "I", "F", "H", "D", "C", "B", "G"},
|
||||
parents: []string{"J"},
|
||||
id: "K",
|
||||
expectedWindowWithGenesisPadding: []string{"J", "I", "F", "D", "H", "C", "B", "G", "A", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindow: []string{"K", "J", "I", "F", "H", "D", "C", "B", "G"},
|
||||
parents: []string{"K"},
|
||||
id: "L",
|
||||
expectedWindowWithGenesisPadding: []string{"K", "J", "I", "F", "D", "H", "C", "B", "G", "A"},
|
||||
},
|
||||
{
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindow: []string{"L", "K", "J", "I", "F", "H", "D", "C", "B", "G"},
|
||||
parents: []string{"L"},
|
||||
id: "M",
|
||||
expectedWindowWithGenesisPadding: []string{"L", "K", "J", "I", "F", "D", "H", "C", "B", "G"},
|
||||
},
|
||||
{
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "H", "D", "C", "B"},
|
||||
parents: []string{"M"},
|
||||
id: "N",
|
||||
expectedWindowWithGenesisPadding: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "B"},
|
||||
},
|
||||
{
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "H", "D", "C"},
|
||||
parents: []string{"N"},
|
||||
id: "O",
|
||||
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -345,7 +345,7 @@ func TestBlockWindow(t *testing.T) {
|
||||
t.Fatalf("BlockWindow: %s", err)
|
||||
}
|
||||
sort.Sort(testutils.NewTestGhostDAGSorter(window, tc, t))
|
||||
if err := checkWindowIDs(window, blockData.expectedWindow, idByBlockMap); err != nil {
|
||||
if err := checkWindowIDs(window, blockData.expectedWindowWithGenesisPadding, idByBlockMap); err != nil {
|
||||
t.Errorf("Unexpected values for window for block %s: %s", blockData.id, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package difficultymanager
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/util/difficulty"
|
||||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/util/difficulty"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type difficultyBlock struct {
|
||||
@@ -29,23 +32,21 @@ func (dm *difficultyManager) getDifficultyBlock(blockHash *externalapi.DomainHas
|
||||
// blocks in the past of startindNode, the sorting is unspecified.
|
||||
// If the number of blocks in the past of startingNode is less then windowSize,
|
||||
// the window will be padded by genesis blocks to achieve a size of windowSize.
|
||||
func (dm *difficultyManager) blockWindow(startingNode *externalapi.DomainHash, windowSize int) (blockWindow,
|
||||
[]*externalapi.DomainHash, error) {
|
||||
|
||||
func (dm *difficultyManager) blockWindow(startingNode *externalapi.DomainHash, windowSize int) (blockWindow, error) {
|
||||
window := make(blockWindow, 0, windowSize)
|
||||
windowHashes, err := dm.dagTraversalManager.BlockWindow(startingNode, windowSize)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, hash := range windowHashes {
|
||||
block, err := dm.getDifficultyBlock(hash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
window = append(window, block)
|
||||
}
|
||||
return window, windowHashes, nil
|
||||
return window, nil
|
||||
}
|
||||
|
||||
func (window blockWindow) minMaxTimestamps() (min, max int64, minIndex, maxIndex int) {
|
||||
@@ -80,3 +81,15 @@ func (window blockWindow) averageTarget() *big.Int {
|
||||
}
|
||||
return averageTarget.Div(averageTarget, big.NewInt(int64(len(window))))
|
||||
}
|
||||
|
||||
func (window blockWindow) medianTimestamp() (int64, error) {
|
||||
if len(window) == 0 {
|
||||
return 0, errors.New("Cannot calculate median timestamp for an empty block window")
|
||||
}
|
||||
timestamps := make([]int64, len(window))
|
||||
for i, node := range window {
|
||||
timestamps[i] = node.timeInMilliseconds
|
||||
}
|
||||
sort.Sort(timeSorter(timestamps))
|
||||
return timestamps[len(timestamps)/2], nil
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package difficultymanager
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/kaspanet/kaspad/util/math"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
@@ -19,7 +17,6 @@ type difficultyManager struct {
|
||||
ghostdagManager model.GHOSTDAGManager
|
||||
ghostdagStore model.GHOSTDAGDataStore
|
||||
headerStore model.BlockHeaderStore
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
dagTopologyManager model.DAGTopologyManager
|
||||
dagTraversalManager model.DAGTraversalManager
|
||||
genesisHash *externalapi.DomainHash
|
||||
@@ -34,7 +31,6 @@ func New(databaseContext model.DBReader,
|
||||
ghostdagManager model.GHOSTDAGManager,
|
||||
ghostdagStore model.GHOSTDAGDataStore,
|
||||
headerStore model.BlockHeaderStore,
|
||||
daaBlocksStore model.DAABlocksStore,
|
||||
dagTopologyManager model.DAGTopologyManager,
|
||||
dagTraversalManager model.DAGTraversalManager,
|
||||
powMax *big.Int,
|
||||
@@ -47,7 +43,6 @@ func New(databaseContext model.DBReader,
|
||||
ghostdagManager: ghostdagManager,
|
||||
ghostdagStore: ghostdagStore,
|
||||
headerStore: headerStore,
|
||||
daaBlocksStore: daaBlocksStore,
|
||||
dagTopologyManager: dagTopologyManager,
|
||||
dagTraversalManager: dagTraversalManager,
|
||||
powMax: powMax,
|
||||
@@ -67,51 +62,39 @@ func (dm *difficultyManager) genesisBits() (uint32, error) {
|
||||
return header.Bits(), nil
|
||||
}
|
||||
|
||||
// StageDAADataAndReturnRequiredDifficulty calculates the DAA window, stages the DAA score and DAA added
|
||||
// blocks, and returns the required difficulty for the given block.
|
||||
// The reason this function both stages DAA data and returns the difficulty is because in order to calculate
|
||||
// both of them we need to calculate the DAA window, which is a relatively heavy operation, so we reuse the
|
||||
// block window instead of recalculating it for the two purposes.
|
||||
// For cases where no staging should happen and the caller only needs to know the difficulty he should
|
||||
// use RequiredDifficulty.
|
||||
func (dm *difficultyManager) StageDAADataAndReturnRequiredDifficulty(blockHash *externalapi.DomainHash) (uint32, error) {
|
||||
// Fetch window of dag.difficultyAdjustmentWindowSize + 1 so we can have dag.difficultyAdjustmentWindowSize block intervals
|
||||
targetsWindow, windowHashes, err := dm.blockWindow(blockHash, dm.difficultyAdjustmentWindowSize+1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = dm.stageDAAScoreAndAddedBlocks(blockHash, windowHashes)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return dm.requiredDifficultyFromTargetsWindow(targetsWindow)
|
||||
}
|
||||
|
||||
// RequiredDifficulty returns the difficulty required for some block
|
||||
func (dm *difficultyManager) RequiredDifficulty(blockHash *externalapi.DomainHash) (uint32, error) {
|
||||
// Fetch window of dag.difficultyAdjustmentWindowSize + 1 so we can have dag.difficultyAdjustmentWindowSize block intervals
|
||||
targetsWindow, _, err := dm.blockWindow(blockHash, dm.difficultyAdjustmentWindowSize+1)
|
||||
parents, err := dm.dagTopologyManager.Parents(blockHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Genesis block or network that doesn't have difficulty adjustment (such as simnet)
|
||||
if len(parents) == 0 || dm.disableDifficultyAdjustment {
|
||||
return dm.genesisBits()
|
||||
}
|
||||
|
||||
// find bluestParent
|
||||
bluestParent, err := dm.ghostdagManager.ChooseSelectedParent(parents...)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
bluestGhostDAG, err := dm.ghostdagStore.Get(dm.databaseContext, bluestParent)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return dm.requiredDifficultyFromTargetsWindow(targetsWindow)
|
||||
}
|
||||
|
||||
func (dm *difficultyManager) requiredDifficultyFromTargetsWindow(targetsWindow blockWindow) (uint32, error) {
|
||||
if dm.disableDifficultyAdjustment {
|
||||
// Not enough blocks for building a difficulty window.
|
||||
if bluestGhostDAG.BlueScore() < uint64(dm.difficultyAdjustmentWindowSize)+1 {
|
||||
return dm.genesisBits()
|
||||
}
|
||||
|
||||
// We need at least 2 blocks to get a timestamp interval
|
||||
// We could instead clamp the timestamp difference to `targetTimePerBlock`,
|
||||
// but then everything will cancel out and we'll get the target from the last block, which will be the same as genesis.
|
||||
if len(targetsWindow) < 2 {
|
||||
return dm.genesisBits()
|
||||
// Fetch window of dag.difficultyAdjustmentWindowSize + 1 so we can have dag.difficultyAdjustmentWindowSize block intervals
|
||||
targetsWindow, err := dm.blockWindow(bluestParent, dm.difficultyAdjustmentWindowSize+1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
windowMinTimestamp, windowMaxTimeStamp, windowsMinIndex, _ := targetsWindow.minMaxTimestamps()
|
||||
|
||||
// Remove the last block from the window so to calculate the average target of dag.difficultyAdjustmentWindowSize blocks
|
||||
targetsWindow.remove(windowsMinIndex)
|
||||
|
||||
@@ -122,66 +105,12 @@ func (dm *difficultyManager) requiredDifficultyFromTargetsWindow(targetsWindow b
|
||||
div := new(big.Int)
|
||||
newTarget := targetsWindow.averageTarget()
|
||||
newTarget.
|
||||
// We need to clamp the timestamp difference to 1 so that we'll never get a 0 target.
|
||||
Mul(newTarget, div.SetInt64(math.MaxInt64(windowMaxTimeStamp-windowMinTimestamp, 1))).
|
||||
Mul(newTarget, div.SetInt64(windowMaxTimeStamp-windowMinTimestamp)).
|
||||
Div(newTarget, div.SetInt64(dm.targetTimePerBlock.Milliseconds())).
|
||||
Div(newTarget, div.SetUint64(uint64(len(targetsWindow))))
|
||||
Div(newTarget, div.SetUint64(uint64(dm.difficultyAdjustmentWindowSize)))
|
||||
if newTarget.Cmp(dm.powMax) > 0 {
|
||||
return difficulty.BigToCompact(dm.powMax), nil
|
||||
}
|
||||
newTargetBits := difficulty.BigToCompact(newTarget)
|
||||
return newTargetBits, nil
|
||||
}
|
||||
|
||||
func (dm *difficultyManager) stageDAAScoreAndAddedBlocks(blockHash *externalapi.DomainHash,
|
||||
windowHashes []*externalapi.DomainHash) error {
|
||||
|
||||
onEnd := logger.LogAndMeasureExecutionTime(log, "stageDAAScoreAndAddedBlocks")
|
||||
defer onEnd()
|
||||
|
||||
daaScore, addedBlocks, err := dm.calculateDaaScoreAndAddedBlocks(blockHash, windowHashes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dm.daaBlocksStore.StageDAAScore(blockHash, daaScore)
|
||||
dm.daaBlocksStore.StageBlockDAAAddedBlocks(blockHash, addedBlocks)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dm *difficultyManager) calculateDaaScoreAndAddedBlocks(blockHash *externalapi.DomainHash,
|
||||
windowHashes []*externalapi.DomainHash) (uint64, []*externalapi.DomainHash, error) {
|
||||
|
||||
if blockHash.Equal(dm.genesisHash) {
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
ghostdagData, err := dm.ghostdagStore.Get(dm.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
mergeSet := make(map[externalapi.DomainHash]struct{}, len(ghostdagData.MergeSet()))
|
||||
for _, hash := range ghostdagData.MergeSet() {
|
||||
mergeSet[*hash] = struct{}{}
|
||||
}
|
||||
|
||||
// TODO: Consider optimizing by breaking the loop once you arrive to the
|
||||
// window block with blue work higher than all non-added merge set blocks.
|
||||
daaAddedBlocks := make([]*externalapi.DomainHash, 0, len(mergeSet))
|
||||
for _, hash := range windowHashes {
|
||||
if _, exists := mergeSet[*hash]; exists {
|
||||
daaAddedBlocks = append(daaAddedBlocks, hash)
|
||||
if len(daaAddedBlocks) == len(mergeSet) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectedParentDAAScore, err := dm.daaBlocksStore.DAAScore(dm.databaseContext, ghostdagData.SelectedParent())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return selectedParentDAAScore + uint64(len(daaAddedBlocks)), daaAddedBlocks, nil
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func TestDifficulty(t *testing.T) {
|
||||
for i := 0; i < params.DifficultyAdjustmentWindowSize; i++ {
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits() != params.GenesisBlock.Header.Bits() {
|
||||
t.Fatalf("As long as the block blue score is less then the difficulty adjustment " +
|
||||
t.Fatalf("As long as the bluest parent's blue score is less then the difficulty adjustment " +
|
||||
"window size, the difficulty should be the same as genesis'")
|
||||
}
|
||||
}
|
||||
@@ -116,10 +116,15 @@ func TestDifficulty(t *testing.T) {
|
||||
|
||||
blockInThePast, tipHash := addBlockWithMinimumTime(tipHash)
|
||||
if blockInThePast.Header.Bits() != tip.Header.Bits() {
|
||||
t.Fatalf("The difficulty should only change when blockInThePast is in the past of a block")
|
||||
t.Fatalf("The difficulty should only change when blockInThePast is in the past of a block bluest parent")
|
||||
}
|
||||
tip = blockInThePast
|
||||
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits() != blockInThePast.Header.Bits() {
|
||||
t.Fatalf("The difficulty should only change when blockInThePast is in the past of a block bluest parent")
|
||||
}
|
||||
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if compareBits(tip.Header.Bits(), blockInThePast.Header.Bits()) >= 0 {
|
||||
t.Fatalf("tip.bits should be smaller than blockInThePast.bits because blockInThePast increased the " +
|
||||
@@ -173,175 +178,37 @@ func TestDifficulty(t *testing.T) {
|
||||
slowBlockTime := tip.Header.TimeInMilliseconds() + params.TargetTimePerBlock.Milliseconds() + 1000
|
||||
slowBlock, tipHash := addBlock(slowBlockTime, tipHash)
|
||||
if slowBlock.Header.Bits() != tip.Header.Bits() {
|
||||
t.Fatalf("The difficulty should only change when slowBlock is in the past of a block")
|
||||
t.Fatalf("The difficulty should only change when slowBlock is in the past of a block bluest parent")
|
||||
}
|
||||
|
||||
tip = slowBlock
|
||||
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits() != slowBlock.Header.Bits() {
|
||||
t.Fatalf("The difficulty should only change when slowBlock is in the past of a block bluest parent")
|
||||
}
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if compareBits(tip.Header.Bits(), slowBlock.Header.Bits()) <= 0 {
|
||||
t.Fatalf("tip.bits should be smaller than slowBlock.bits because slowBlock decreased the block" +
|
||||
" rate, so the difficulty should decrease as well")
|
||||
}
|
||||
|
||||
// Here we create two chains: a chain of blue blocks, and a chain of red blocks with
|
||||
// very low timestamps. Because the red blocks should be part of the difficulty
|
||||
// window, their low timestamps should lower the difficulty, and we check it by
|
||||
// comparing the bits of two blocks with the same blue score, one with the red
|
||||
// blocks in its past and one without.
|
||||
_, tipHash = addBlock(0, tipHash)
|
||||
splitBlockHash := tipHash
|
||||
blueTipHash := splitBlockHash
|
||||
for i := 0; i < params.DifficultyAdjustmentWindowSize; i++ {
|
||||
_, blueTipHash = addBlock(0, blueTipHash)
|
||||
for i := 0; i < 100; i++ {
|
||||
_, tipHash = addBlock(0, tipHash)
|
||||
}
|
||||
blueTipHash := tipHash
|
||||
|
||||
redChainTipHash := splitBlockHash
|
||||
const redChainLength = 10
|
||||
for i := 0; i < redChainLength; i++ {
|
||||
for i := 0; i < 10; i++ {
|
||||
_, redChainTipHash = addBlockWithMinimumTime(redChainTipHash)
|
||||
}
|
||||
tipWithRedPast, _ := addBlock(0, redChainTipHash, blueTipHash)
|
||||
tipWithoutRedPast, _ := addBlock(0, blueTipHash)
|
||||
if tipWithRedPast.Header.Bits() <= tipWithoutRedPast.Header.Bits() {
|
||||
t.Fatalf("tipWithRedPast.bits should be greater than tipWithoutRedPast.bits because the red blocks" +
|
||||
" blocks have very low timestamp and should lower the difficulty")
|
||||
}
|
||||
|
||||
// We repeat the test, but now we make the blue chain longer in order to filter
|
||||
// out the red blocks from the window, and check that the red blocks don't
|
||||
// affect the difficulty.
|
||||
blueTipHash = splitBlockHash
|
||||
for i := 0; i < params.DifficultyAdjustmentWindowSize+redChainLength+1; i++ {
|
||||
_, blueTipHash = addBlock(0, blueTipHash)
|
||||
}
|
||||
|
||||
redChainTipHash = splitBlockHash
|
||||
for i := 0; i < redChainLength; i++ {
|
||||
_, redChainTipHash = addBlockWithMinimumTime(redChainTipHash)
|
||||
}
|
||||
tipWithRedPast, _ = addBlock(0, redChainTipHash, blueTipHash)
|
||||
tipWithoutRedPast, _ = addBlock(0, blueTipHash)
|
||||
if tipWithRedPast.Header.Bits() != tipWithoutRedPast.Header.Bits() {
|
||||
t.Fatalf("tipWithoutRedPast.bits should be the same as tipWithRedPast.bits because the red blocks" +
|
||||
" are not part of the difficulty window")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDAAScore(t *testing.T) {
|
||||
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
|
||||
params.DifficultyAdjustmentWindowSize = 264
|
||||
|
||||
factory := consensus.NewFactory()
|
||||
tc, teardown, err := factory.NewTestConsensus(params, false, "TestDifficulty")
|
||||
if err != nil {
|
||||
t.Fatalf("Error setting up consensus: %+v", err)
|
||||
}
|
||||
defer teardown(false)
|
||||
|
||||
// We create a small DAG in order to skip from block with blue score of 1 directly to 3
|
||||
split1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
block, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
|
||||
blockBlueScore3, _, err := tc.AddBlock([]*externalapi.DomainHash{split1Hash, block}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
|
||||
tipHash := blockBlueScore3
|
||||
blockBlueScore3DAAScore, err := tc.DAABlocksStore().DAAScore(tc.DatabaseContext(), tipHash)
|
||||
if err != nil {
|
||||
t.Fatalf("DAAScore: %+v", err)
|
||||
}
|
||||
|
||||
blockBlueScore3ExpectedDAAScore := uint64(2)
|
||||
if blockBlueScore3DAAScore != blockBlueScore3ExpectedDAAScore {
|
||||
t.Fatalf("DAA score is expected to be %d but got %d", blockBlueScore3ExpectedDAAScore, blockBlueScore3ExpectedDAAScore)
|
||||
}
|
||||
tipDAAScore := blockBlueScore3ExpectedDAAScore
|
||||
|
||||
for i := uint64(0); i < 10; i++ {
|
||||
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
tipDAAScore, err = tc.DAABlocksStore().DAAScore(tc.DatabaseContext(), tipHash)
|
||||
if err != nil {
|
||||
t.Fatalf("DAAScore: %+v", err)
|
||||
}
|
||||
|
||||
expectedDAAScore := blockBlueScore3ExpectedDAAScore + i + 1
|
||||
if tipDAAScore != expectedDAAScore {
|
||||
t.Fatalf("DAA score is expected to be %d but got %d", expectedDAAScore, tipDAAScore)
|
||||
}
|
||||
}
|
||||
|
||||
split2Hash := tipHash
|
||||
split2DAAScore := tipDAAScore
|
||||
for i := uint64(0); i < uint64(params.DifficultyAdjustmentWindowSize)-1; i++ {
|
||||
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
tipDAAScore, err = tc.DAABlocksStore().DAAScore(tc.DatabaseContext(), tipHash)
|
||||
if err != nil {
|
||||
t.Fatalf("DAAScore: %+v", err)
|
||||
}
|
||||
|
||||
expectedDAAScore := split2DAAScore + i + 1
|
||||
if tipDAAScore != expectedDAAScore {
|
||||
t.Fatalf("DAA score is expected to be %d but got %d", expectedDAAScore, split2DAAScore)
|
||||
}
|
||||
}
|
||||
|
||||
// This block should have blue score of 2 so it shouldn't be added to the DAA window of a merging block
|
||||
blockAboveSplit1, _, err := tc.AddBlock([]*externalapi.DomainHash{split1Hash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
|
||||
// This block is in the anticone of params.DifficultyAdjustmentWindowSize-1 blocks, so it must be part
|
||||
// of the DAA window of a merging block
|
||||
blockAboveSplit2, _, err := tc.AddBlock([]*externalapi.DomainHash{split2Hash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
|
||||
currentSelectedTipDAAScore := tipDAAScore
|
||||
currentSelectedTip := tipHash
|
||||
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{blockAboveSplit1, blockAboveSplit2, tipHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %+v", err)
|
||||
}
|
||||
|
||||
tipDAAScore, err = tc.DAABlocksStore().DAAScore(tc.DatabaseContext(), tipHash)
|
||||
if err != nil {
|
||||
t.Fatalf("DAAScore: %+v", err)
|
||||
}
|
||||
|
||||
// The DAA score should be increased only by 2, because 1 of the 3 merged blocks
|
||||
// is not in the DAA window
|
||||
expectedDAAScore := currentSelectedTipDAAScore + 2
|
||||
if tipDAAScore != expectedDAAScore {
|
||||
t.Fatalf("DAA score is expected to be %d but got %d", expectedDAAScore, tipDAAScore)
|
||||
}
|
||||
|
||||
tipDAAAddedBlocks, err := tc.DAABlocksStore().DAAAddedBlocks(tc.DatabaseContext(), tipHash)
|
||||
if err != nil {
|
||||
t.Fatalf("DAAScore: %+v", err)
|
||||
}
|
||||
|
||||
// blockAboveSplit2 should be excluded from the DAA added blocks because it's not in the tip's
|
||||
// DAA window.
|
||||
expectedDAABlocks := []*externalapi.DomainHash{blockAboveSplit2, currentSelectedTip}
|
||||
if !externalapi.HashesEqual(tipDAAAddedBlocks, expectedDAABlocks) {
|
||||
t.Fatalf("DAA added blocks are expected to be %s but got %s", expectedDAABlocks, tipDAAAddedBlocks)
|
||||
if tipWithoutRedPast.Header.Bits() != tipWithRedPast.Header.Bits() {
|
||||
t.Fatalf("tipWithoutRedPast.bits should be the same as tipWithRedPast.bits because red blocks" +
|
||||
" shouldn't affect the difficulty")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package difficultymanager
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
)
|
||||
|
||||
var log = logger.RegisterSubSystem("DAA")
|
||||
@@ -2,31 +2,26 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package sorters
|
||||
package difficultymanager
|
||||
|
||||
import "sort"
|
||||
|
||||
// Int64Slice implements sort.Interface to allow a slice of timestamps to
|
||||
// timeSorter implements sort.Interface to allow a slice of timestamps to
|
||||
// be sorted.
|
||||
type Int64Slice []int64
|
||||
type timeSorter []int64
|
||||
|
||||
// Len returns the number of timestamps in the slice. It is part of the
|
||||
// sort.Interface implementation.
|
||||
func (s Int64Slice) Len() int {
|
||||
func (s timeSorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// Swap swaps the timestamps at the passed indices. It is part of the
|
||||
// sort.Interface implementation.
|
||||
func (s Int64Slice) Swap(i, j int) {
|
||||
func (s timeSorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Less returns whether the timstamp with index i should sort before the
|
||||
// timestamp with index j. It is part of the sort.Interface implementation.
|
||||
func (s Int64Slice) Less(i, j int) bool {
|
||||
func (s timeSorter) Less(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
}
|
||||
|
||||
// Sort is a convenience method: s.Sort() calls sort.Sort(s).
|
||||
func (s Int64Slice) Sort() { sort.Sort(s) }
|
||||
@@ -1,7 +1,6 @@
|
||||
package pastmediantimemanager
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/sorters"
|
||||
"sort"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
@@ -20,8 +19,6 @@ type pastMedianTimeManager struct {
|
||||
|
||||
blockHeaderStore model.BlockHeaderStore
|
||||
ghostdagDataStore model.GHOSTDAGDataStore
|
||||
|
||||
genesisHash *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// New instantiates a new PastMedianTimeManager
|
||||
@@ -29,8 +26,7 @@ func New(timestampDeviationTolerance int,
|
||||
databaseContext model.DBReader,
|
||||
dagTraversalManager model.DAGTraversalManager,
|
||||
blockHeaderStore model.BlockHeaderStore,
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
genesisHash *externalapi.DomainHash) model.PastMedianTimeManager {
|
||||
ghostdagDataStore model.GHOSTDAGDataStore) model.PastMedianTimeManager {
|
||||
|
||||
return &pastMedianTimeManager{
|
||||
timestampDeviationTolerance: timestampDeviationTolerance,
|
||||
@@ -40,24 +36,32 @@ func New(timestampDeviationTolerance int,
|
||||
|
||||
blockHeaderStore: blockHeaderStore,
|
||||
ghostdagDataStore: ghostdagDataStore,
|
||||
genesisHash: genesisHash,
|
||||
}
|
||||
}
|
||||
|
||||
// PastMedianTime returns the past median time for some block
|
||||
func (pmtm *pastMedianTimeManager) PastMedianTime(blockHash *externalapi.DomainHash) (int64, error) {
|
||||
window, err := pmtm.dagTraversalManager.BlockWindow(blockHash, 2*pmtm.timestampDeviationTolerance-1)
|
||||
blockGHOSTDAGData, err := pmtm.ghostdagDataStore.Get(pmtm.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(window) == 0 {
|
||||
header, err := pmtm.blockHeaderStore.BlockHeader(pmtm.databaseContext, pmtm.genesisHash)
|
||||
selectedParentHash := blockGHOSTDAGData.SelectedParent()
|
||||
|
||||
// Genesis block
|
||||
if selectedParentHash == nil {
|
||||
header, err := pmtm.blockHeaderStore.BlockHeader(pmtm.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return header.TimeInMilliseconds(), nil
|
||||
}
|
||||
|
||||
window, err := pmtm.dagTraversalManager.BlockWindow(selectedParentHash, 2*pmtm.timestampDeviationTolerance-1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return pmtm.windowMedianTimestamp(window)
|
||||
}
|
||||
|
||||
@@ -75,7 +79,9 @@ func (pmtm *pastMedianTimeManager) windowMedianTimestamp(window []*externalapi.D
|
||||
timestamps[i] = blockHeader.TimeInMilliseconds()
|
||||
}
|
||||
|
||||
sort.Sort(sorters.Int64Slice(timestamps))
|
||||
sort.Slice(timestamps, func(i, j int) bool {
|
||||
return timestamps[i] < timestamps[j]
|
||||
})
|
||||
|
||||
return timestamps[len(timestamps)/2], nil
|
||||
}
|
||||
|
||||
@@ -47,19 +47,19 @@ func TestPastMedianTime(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
blockNumber: 263,
|
||||
expectedMillisecondsSinceGenesis: 132000,
|
||||
expectedMillisecondsSinceGenesis: 130000,
|
||||
},
|
||||
{
|
||||
blockNumber: 271,
|
||||
expectedMillisecondsSinceGenesis: 139000,
|
||||
expectedMillisecondsSinceGenesis: 138000,
|
||||
},
|
||||
{
|
||||
blockNumber: 241,
|
||||
expectedMillisecondsSinceGenesis: 121000,
|
||||
expectedMillisecondsSinceGenesis: 108000,
|
||||
},
|
||||
{
|
||||
blockNumber: 5,
|
||||
expectedMillisecondsSinceGenesis: 3000,
|
||||
expectedMillisecondsSinceGenesis: 0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestPruning(t *testing.T) {
|
||||
},
|
||||
"dag-for-test-pruning.json": {
|
||||
dagconfig.MainnetParams.Name: "503",
|
||||
dagconfig.TestnetParams.Name: "502",
|
||||
dagconfig.TestnetParams.Name: "503",
|
||||
dagconfig.DevnetParams.Name: "503",
|
||||
dagconfig.SimnetParams.Name: "502",
|
||||
},
|
||||
|
||||
@@ -28,7 +28,6 @@ type pruningManager struct {
|
||||
blocksStore model.BlockStore
|
||||
blockHeaderStore model.BlockHeaderStore
|
||||
utxoDiffStore model.UTXODiffStore
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
|
||||
isArchivalNode bool
|
||||
genesisHash *externalapi.DomainHash
|
||||
@@ -43,18 +42,17 @@ func New(
|
||||
dagTraversalManager model.DAGTraversalManager,
|
||||
dagTopologyManager model.DAGTopologyManager,
|
||||
consensusStateManager model.ConsensusStateManager,
|
||||
|
||||
consensusStateStore model.ConsensusStateStore,
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
pruningStore model.PruningStore,
|
||||
blockStatusStore model.BlockStatusStore,
|
||||
headerSelectedTipStore model.HeaderSelectedTipStore,
|
||||
|
||||
multiSetStore model.MultisetStore,
|
||||
acceptanceDataStore model.AcceptanceDataStore,
|
||||
blocksStore model.BlockStore,
|
||||
blockHeaderStore model.BlockHeaderStore,
|
||||
utxoDiffStore model.UTXODiffStore,
|
||||
daaBlocksStore model.DAABlocksStore,
|
||||
|
||||
isArchivalNode bool,
|
||||
genesisHash *externalapi.DomainHash,
|
||||
@@ -77,7 +75,6 @@ func New(
|
||||
blockHeaderStore: blockHeaderStore,
|
||||
utxoDiffStore: utxoDiffStore,
|
||||
headerSelectedTipStore: headerSelectedTipStore,
|
||||
daaBlocksStore: daaBlocksStore,
|
||||
isArchivalNode: isArchivalNode,
|
||||
genesisHash: genesisHash,
|
||||
pruningDepth: pruningDepth,
|
||||
@@ -351,7 +348,6 @@ func (pm *pruningManager) deleteBlock(blockHash *externalapi.DomainHash) (alread
|
||||
pm.acceptanceDataStore.Delete(blockHash)
|
||||
pm.blocksStore.Delete(blockHash)
|
||||
pm.utxoDiffStore.Delete(blockHash)
|
||||
pm.daaBlocksStore.Delete(blockHash)
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
package reachabilitymanager_test
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReachabilityIsDAGAncestorOf(t *testing.T) {
|
||||
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
|
||||
|
||||
factory := consensus.NewFactory()
|
||||
tc, teardown, err := factory.NewTestConsensus(params, false, "TestReachabilityIsDAGAncestorOf")
|
||||
if err != nil {
|
||||
t.Fatalf("Error setting up consensus: %+v", err)
|
||||
}
|
||||
defer teardown(false)
|
||||
|
||||
// A <- B - - - -
|
||||
// / \ \
|
||||
// genesis \ \ sharedBlock
|
||||
// \ \ /
|
||||
// C <- D - - - - /
|
||||
genesisHash := params.GenesisHash
|
||||
blockHashA, _, err := tc.AddBlock([]*externalapi.DomainHash{genesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %v", err)
|
||||
}
|
||||
|
||||
blockHashB, _, err := tc.AddBlock([]*externalapi.DomainHash{blockHashA}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %v", err)
|
||||
}
|
||||
|
||||
blockHashC, _, err := tc.AddBlock([]*externalapi.DomainHash{genesisHash}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %v", err)
|
||||
}
|
||||
|
||||
blockHashD, _, err := tc.AddBlock([]*externalapi.DomainHash{blockHashA, blockHashC}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %v", err)
|
||||
}
|
||||
|
||||
sharedBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{blockHashB, blockHashD}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddBlock: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
firstBlockHash *externalapi.DomainHash
|
||||
secondBlockHash *externalapi.DomainHash
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
firstBlockHash: blockHashA,
|
||||
secondBlockHash: blockHashA,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
firstBlockHash: genesisHash,
|
||||
secondBlockHash: blockHashA,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
firstBlockHash: genesisHash,
|
||||
secondBlockHash: sharedBlockHash,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
firstBlockHash: blockHashC,
|
||||
secondBlockHash: blockHashD,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
firstBlockHash: blockHashA,
|
||||
secondBlockHash: blockHashD,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
firstBlockHash: blockHashC,
|
||||
secondBlockHash: blockHashB,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
firstBlockHash: blockHashB,
|
||||
secondBlockHash: blockHashD,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
firstBlockHash: blockHashB,
|
||||
secondBlockHash: blockHashA,
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
isDAGAncestorOf, err := tc.ReachabilityManager().IsDAGAncestorOf(test.firstBlockHash, test.secondBlockHash)
|
||||
if err != nil {
|
||||
t.Fatalf("IsDAGAncestorOf: %v", err)
|
||||
}
|
||||
if isDAGAncestorOf != test.expectedResult {
|
||||
t.Fatalf("IsDAGAncestorOf: should returns %v but got %v", test.expectedResult, isDAGAncestorOf)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -11,28 +11,29 @@ import (
|
||||
// `maxBlueScoreDifference`, if non-zero.
|
||||
// The result excludes lowHash and includes highHash. If lowHash == highHash, returns nothing.
|
||||
func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.DomainHash,
|
||||
maxBlueScoreDifference uint64) (hashes []*externalapi.DomainHash, actualHighHash *externalapi.DomainHash, err error) {
|
||||
maxBlueScoreDifference uint64) ([]*externalapi.DomainHash, error) {
|
||||
|
||||
// If lowHash is not in the selectedParentChain of highHash - SelectedChildIterator will fail.
|
||||
// Therefore, we traverse down lowHash's selectedParentChain until we reach a block that is in
|
||||
// highHash's selectedParentChain.
|
||||
// We keep originalLowHash to filter out blocks in it's past later down the road
|
||||
originalLowHash := lowHash
|
||||
var err error
|
||||
lowHash, err = sm.findLowHashInHighHashSelectedParentChain(lowHash, highHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lowBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, lowHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
highBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, highHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
if lowBlockGHOSTDAGData.BlueScore() > highBlockGHOSTDAGData.BlueScore() {
|
||||
return nil, nil, errors.Errorf("low hash blueScore > high hash blueScore (%d > %d)",
|
||||
return nil, errors.Errorf("low hash blueScore > high hash blueScore (%d > %d)",
|
||||
lowBlockGHOSTDAGData.BlueScore(), highBlockGHOSTDAGData.BlueScore())
|
||||
}
|
||||
|
||||
@@ -48,7 +49,7 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
||||
// blue.
|
||||
highHash, err = sm.findHighHashAccordingToMaxBlueScoreDifference(lowHash, highHash, maxBlueScoreDifference, highBlockGHOSTDAGData, lowBlockGHOSTDAGData)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,13 +57,13 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
||||
blockHashes := []*externalapi.DomainHash{}
|
||||
iterator, err := sm.dagTraversalManager.SelectedChildIterator(highHash, lowHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
defer iterator.Close()
|
||||
for ok := iterator.First(); ok; ok = iterator.Next() {
|
||||
current, err := iterator.Get()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
// Both blue and red merge sets are topologically sorted, but not the concatenation of the two.
|
||||
// We require the blocks to be topologically sorted. In addition, for optimal performance,
|
||||
@@ -72,14 +73,14 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
||||
// Therefore we first append the selectedParent, then the rest of blocks in ghostdag order.
|
||||
sortedMergeSet, err := sm.getSortedMergeSet(current)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// append to blockHashes all blocks in sortedMergeSet which are not in the past of originalLowHash
|
||||
for _, blockHash := range sortedMergeSet {
|
||||
isInPastOfOriginalLowHash, err := sm.dagTopologyManager.IsAncestorOf(blockHash, originalLowHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
if isInPastOfOriginalLowHash {
|
||||
continue
|
||||
@@ -93,7 +94,7 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
||||
blockHashes = append(blockHashes, highHash)
|
||||
}
|
||||
|
||||
return blockHashes, highHash, nil
|
||||
return blockHashes, nil
|
||||
}
|
||||
|
||||
func (sm *syncManager) getSortedMergeSet(current *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
||||
@@ -225,7 +226,7 @@ func (sm *syncManager) missingBlockBodyHashes(highHash *externalapi.DomainHash)
|
||||
lowHash, highHash)
|
||||
}
|
||||
|
||||
hashesBetween, _, err := sm.antiPastHashesBetween(lowHash, highHash, 0)
|
||||
hashesBetween, err := sm.antiPastHashesBetween(lowHash, highHash, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func New(
|
||||
}
|
||||
|
||||
func (sm *syncManager) GetHashesBetween(lowHash, highHash *externalapi.DomainHash,
|
||||
maxBlueScoreDifference uint64) (hashes []*externalapi.DomainHash, actualHighHash *externalapi.DomainHash, err error) {
|
||||
maxBlueScoreDifference uint64) ([]*externalapi.DomainHash, error) {
|
||||
|
||||
onEnd := logger.LogAndMeasureExecutionTime(log, "GetHashesBetween")
|
||||
defer onEnd()
|
||||
|
||||
@@ -55,7 +55,7 @@ func TestSyncManager_GetHashesBetween(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, blockHash := range expectedOrder {
|
||||
empty, _, err := tc.SyncManager().GetHashesBetween(blockHash, blockHash, math.MaxUint64)
|
||||
empty, err := tc.SyncManager().GetHashesBetween(blockHash, blockHash, math.MaxUint64)
|
||||
if err != nil {
|
||||
t.Fatalf("TestSyncManager_GetHashesBetween failed returning 0 hashes on the %d'th block: %v", i, err)
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func TestSyncManager_GetHashesBetween(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
actualOrder, _, err := tc.SyncManager().GetHashesBetween(params.GenesisHash, expectedOrder[len(expectedOrder)-1], math.MaxUint64)
|
||||
actualOrder, err := tc.SyncManager().GetHashesBetween(params.GenesisHash, expectedOrder[len(expectedOrder)-1], math.MaxUint64)
|
||||
if err != nil {
|
||||
t.Fatalf("TestSyncManager_GetHashesBetween failed returning actualOrder: %v", err)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package transactionvalidator
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
||||
@@ -55,25 +54,26 @@ func (v *transactionValidator) ValidateTransactionInContextAndPopulateMassAndFee
|
||||
func (v *transactionValidator) checkTransactionCoinbaseMaturity(
|
||||
povBlockHash *externalapi.DomainHash, tx *externalapi.DomainTransaction) error {
|
||||
|
||||
povDAAScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, povBlockHash)
|
||||
ghostdagData, err := v.ghostdagDataStore.Get(v.databaseContext, povBlockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBlueScore := ghostdagData.BlueScore()
|
||||
var missingOutpoints []*externalapi.DomainOutpoint
|
||||
for _, input := range tx.Inputs {
|
||||
utxoEntry := input.UTXOEntry
|
||||
if utxoEntry == nil {
|
||||
missingOutpoints = append(missingOutpoints, &input.PreviousOutpoint)
|
||||
} else if utxoEntry.IsCoinbase() {
|
||||
originDAAScore := utxoEntry.BlockDAAScore()
|
||||
daaScoreSincePrev := povDAAScore - originDAAScore
|
||||
if daaScoreSincePrev < v.blockCoinbaseMaturity {
|
||||
originBlueScore := utxoEntry.BlockBlueScore()
|
||||
blueScoreSincePrev := txBlueScore - originBlueScore
|
||||
if blueScoreSincePrev < v.blockCoinbaseMaturity {
|
||||
return errors.Wrapf(ruleerrors.ErrImmatureSpend, "tried to spend coinbase "+
|
||||
"transaction output %s from DAA score %d "+
|
||||
"to DAA score %d before required maturity "+
|
||||
"transaction output %s from blue score %d "+
|
||||
"to blue score %d before required maturity "+
|
||||
"of %d", input.PreviousOutpoint,
|
||||
originDAAScore, povDAAScore,
|
||||
originBlueScore, txBlueScore,
|
||||
v.blockCoinbaseMaturity)
|
||||
}
|
||||
}
|
||||
@@ -161,12 +161,12 @@ func (v *transactionValidator) checkTransactionSequenceLock(povBlockHash *extern
|
||||
return err
|
||||
}
|
||||
|
||||
daaScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, povBlockHash)
|
||||
ghostdagData, err := v.ghostdagDataStore.Get(v.databaseContext, povBlockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !v.sequenceLockActive(sequenceLock, daaScore, medianTime) {
|
||||
if !v.sequenceLockActive(sequenceLock, ghostdagData.BlueScore(), medianTime) {
|
||||
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "block contains "+
|
||||
"transaction whose input sequence "+
|
||||
"locks are not met")
|
||||
@@ -178,8 +178,6 @@ func (v *transactionValidator) checkTransactionSequenceLock(povBlockHash *extern
|
||||
func (v *transactionValidator) validateTransactionScripts(tx *externalapi.DomainTransaction) error {
|
||||
|
||||
var missingOutpoints []*externalapi.DomainOutpoint
|
||||
sighashReusedValues := &consensushashing.SighashReusedValues{}
|
||||
|
||||
for i, input := range tx.Inputs {
|
||||
// Create a new script engine for the script pair.
|
||||
sigScript := input.SignatureScript
|
||||
@@ -190,7 +188,8 @@ func (v *transactionValidator) validateTransactionScripts(tx *externalapi.Domain
|
||||
}
|
||||
|
||||
scriptPubKey := utxoEntry.ScriptPublicKey()
|
||||
vm, err := txscript.NewEngine(scriptPubKey, tx, i, txscript.ScriptNoFlags, v.sigCache, sighashReusedValues)
|
||||
vm, err := txscript.NewEngine(scriptPubKey, tx,
|
||||
i, txscript.ScriptNoFlags, v.sigCache)
|
||||
if err != nil {
|
||||
return errors.Wrapf(ruleerrors.ErrScriptMalformed, "failed to parse input "+
|
||||
"%d which references output %s - "+
|
||||
@@ -222,7 +221,7 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(
|
||||
// A value of -1 for each relative lock type represents a relative time
|
||||
// lock value that will allow a transaction to be included in a block
|
||||
// at any given height or time.
|
||||
sequenceLock := &sequenceLock{Milliseconds: -1, BlockDAAScore: -1}
|
||||
sequenceLock := &sequenceLock{Milliseconds: -1, BlockBlueScore: -1}
|
||||
|
||||
// Sequence locks don't apply to coinbase transactions Therefore, we
|
||||
// return sequence lock values of -1 indicating that this transaction
|
||||
@@ -239,7 +238,10 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(
|
||||
continue
|
||||
}
|
||||
|
||||
inputDAAScore := utxoEntry.BlockDAAScore()
|
||||
// If the input blue score is set to the mempool blue score, then we
|
||||
// assume the transaction makes it into the next block when
|
||||
// evaluating its sequence blocks.
|
||||
inputBlueScore := utxoEntry.BlockBlueScore()
|
||||
|
||||
// Given a sequence number, we apply the relative time lock
|
||||
// mask in order to obtain the time lock delta required before
|
||||
@@ -267,21 +269,16 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(
|
||||
baseHash := povBlockHash
|
||||
|
||||
for {
|
||||
selectedParentDAAScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, povBlockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if selectedParentDAAScore <= inputDAAScore {
|
||||
break
|
||||
}
|
||||
|
||||
selectedParentGHOSTDAGData, err := v.ghostdagDataStore.Get(v.databaseContext,
|
||||
baseGHOSTDAGData.SelectedParent())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if selectedParentGHOSTDAGData.BlueScore() <= inputBlueScore {
|
||||
break
|
||||
}
|
||||
|
||||
baseHash = baseGHOSTDAGData.SelectedParent()
|
||||
baseGHOSTDAGData = selectedParentGHOSTDAGData
|
||||
}
|
||||
@@ -304,12 +301,12 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(
|
||||
default:
|
||||
// The relative lock-time for this input is expressed
|
||||
// in blocks so we calculate the relative offset from
|
||||
// the input's DAA score as its converted absolute
|
||||
// the input's blue score as its converted absolute
|
||||
// lock-time. We subtract one from the relative lock in
|
||||
// order to maintain the original lockTime semantics.
|
||||
blockDAAScore := int64(inputDAAScore) + relativeLock - 1
|
||||
if blockDAAScore > sequenceLock.BlockDAAScore {
|
||||
sequenceLock.BlockDAAScore = blockDAAScore
|
||||
blockBlueScore := int64(inputBlueScore) + relativeLock - 1
|
||||
if blockBlueScore > sequenceLock.BlockBlueScore {
|
||||
sequenceLock.BlockBlueScore = blockBlueScore
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,27 +318,27 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(
|
||||
}
|
||||
|
||||
// sequenceLock represents the converted relative lock-time in seconds, and
|
||||
// absolute block-daa-score for a transaction input's relative lock-times.
|
||||
// absolute block-blue-score for a transaction input's relative lock-times.
|
||||
// According to sequenceLock, after the referenced input has been confirmed
|
||||
// within a block, a transaction spending that input can be included into a
|
||||
// block either after 'seconds' (according to past median time), or once the
|
||||
// 'BlockDAAScore' has been reached.
|
||||
// 'BlockBlueScore' has been reached.
|
||||
type sequenceLock struct {
|
||||
Milliseconds int64
|
||||
BlockDAAScore int64
|
||||
Milliseconds int64
|
||||
BlockBlueScore int64
|
||||
}
|
||||
|
||||
// sequenceLockActive determines if a transaction's sequence locks have been
|
||||
// met, meaning that all the inputs of a given transaction have reached a
|
||||
// DAA score or time sufficient for their relative lock-time maturity.
|
||||
func (v *transactionValidator) sequenceLockActive(sequenceLock *sequenceLock, blockDAAScore uint64,
|
||||
// blue score or time sufficient for their relative lock-time maturity.
|
||||
func (v *transactionValidator) sequenceLockActive(sequenceLock *sequenceLock, blockBlueScore uint64,
|
||||
medianTimePast int64) bool {
|
||||
|
||||
// If either the milliseconds, or DAA score relative-lock time has not yet
|
||||
// If either the milliseconds, or blue score relative-lock time has not yet
|
||||
// reached, then the transaction is not yet mature according to its
|
||||
// sequence locks.
|
||||
if sequenceLock.Milliseconds >= medianTimePast ||
|
||||
sequenceLock.BlockDAAScore >= int64(blockDAAScore) {
|
||||
sequenceLock.BlockBlueScore >= int64(blockBlueScore) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -9,34 +9,34 @@ import (
|
||||
// works as expected in all possible combinations/scenarios.
|
||||
func TestSequenceLocksActive(t *testing.T) {
|
||||
tests := []struct {
|
||||
seqLock sequenceLock
|
||||
blockDAAScore uint64
|
||||
mtp mstime.Time
|
||||
seqLock sequenceLock
|
||||
blockBlueScore uint64
|
||||
mtp mstime.Time
|
||||
|
||||
want bool
|
||||
}{
|
||||
// Block based sequence lock with equal block DAA score.
|
||||
{seqLock: sequenceLock{-1, 1000}, blockDAAScore: 1001, mtp: mstime.UnixMilliseconds(9), want: true},
|
||||
// Block based sequence lock with equal block blue score.
|
||||
{seqLock: sequenceLock{-1, 1000}, blockBlueScore: 1001, mtp: mstime.UnixMilliseconds(9), want: true},
|
||||
|
||||
// Time based sequence lock with mtp past the absolute time.
|
||||
{seqLock: sequenceLock{30, -1}, blockDAAScore: 2, mtp: mstime.UnixMilliseconds(31), want: true},
|
||||
{seqLock: sequenceLock{30, -1}, blockBlueScore: 2, mtp: mstime.UnixMilliseconds(31), want: true},
|
||||
|
||||
// Block based sequence lock with current DAA score below seq lock block DAA score.
|
||||
{seqLock: sequenceLock{-1, 1000}, blockDAAScore: 90, mtp: mstime.UnixMilliseconds(9), want: false},
|
||||
// Block based sequence lock with current blue score below seq lock block blue score.
|
||||
{seqLock: sequenceLock{-1, 1000}, blockBlueScore: 90, mtp: mstime.UnixMilliseconds(9), want: false},
|
||||
|
||||
// Time based sequence lock with current time before lock time.
|
||||
{seqLock: sequenceLock{30, -1}, blockDAAScore: 2, mtp: mstime.UnixMilliseconds(29), want: false},
|
||||
{seqLock: sequenceLock{30, -1}, blockBlueScore: 2, mtp: mstime.UnixMilliseconds(29), want: false},
|
||||
|
||||
// Block based sequence lock at the same DAA score, so shouldn't yet be active.
|
||||
{seqLock: sequenceLock{-1, 1000}, blockDAAScore: 1000, mtp: mstime.UnixMilliseconds(9), want: false},
|
||||
// Block based sequence lock at the same blue score, so shouldn't yet be active.
|
||||
{seqLock: sequenceLock{-1, 1000}, blockBlueScore: 1000, mtp: mstime.UnixMilliseconds(9), want: false},
|
||||
|
||||
// Time based sequence lock with current time equal to lock time, so shouldn't yet be active.
|
||||
{seqLock: sequenceLock{30, -1}, blockDAAScore: 2, mtp: mstime.UnixMilliseconds(30), want: false},
|
||||
{seqLock: sequenceLock{30, -1}, blockBlueScore: 2, mtp: mstime.UnixMilliseconds(30), want: false},
|
||||
}
|
||||
|
||||
validator := transactionValidator{}
|
||||
for i, test := range tests {
|
||||
got := validator.sequenceLockActive(&test.seqLock, test.blockDAAScore, test.mtp.UnixMilliseconds())
|
||||
got := validator.sequenceLockActive(&test.seqLock, test.blockBlueScore, test.mtp.UnixMilliseconds())
|
||||
if got != test.want {
|
||||
t.Fatalf("SequenceLockActive #%d got %v want %v", i, got, test.want)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
|
||||
"github.com/pkg/errors"
|
||||
@@ -26,6 +27,10 @@ func (v *transactionValidator) ValidateTransactionInIsolation(tx *externalapi.Do
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = v.checkTransactionPayloadHash(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = v.checkGasInBuiltInOrNativeTransactions(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -125,6 +130,18 @@ func (v *transactionValidator) checkCoinbaseLength(tx *externalapi.DomainTransac
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *transactionValidator) checkTransactionPayloadHash(tx *externalapi.DomainTransaction) error {
|
||||
if tx.SubnetworkID != subnetworks.SubnetworkIDNative {
|
||||
payloadHash := hashes.PayloadHash(tx.Payload)
|
||||
if !tx.PayloadHash.Equal(payloadHash) {
|
||||
return errors.Wrapf(ruleerrors.ErrInvalidPayloadHash, "invalid payload hash")
|
||||
}
|
||||
} else if tx.PayloadHash != (externalapi.DomainHash{}) {
|
||||
return errors.Wrapf(ruleerrors.ErrInvalidPayloadHash, "unexpected non-empty payload hash in native subnetwork")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *transactionValidator) checkGasInBuiltInOrNativeTransactions(tx *externalapi.DomainTransaction) error {
|
||||
// Transactions in native, registry and coinbase subnetworks must have Gas = 0
|
||||
if subnetworks.IsBuiltInOrNative(tx.SubnetworkID) && tx.Gas > 0 {
|
||||
|
||||
@@ -3,6 +3,8 @@ package transactionvalidator_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
@@ -101,6 +103,20 @@ func TestValidateTransactionInIsolation(t *testing.T) {
|
||||
tx.Payload = []byte{1}
|
||||
},
|
||||
ruleerrors.ErrInvalidPayload},
|
||||
{"invalid payload hash", 1, 1, 0,
|
||||
externalapi.DomainSubnetworkID{123},
|
||||
&txSubnetworkData{externalapi.DomainSubnetworkID{123}, 0, []byte{1}},
|
||||
func(tx *externalapi.DomainTransaction) {
|
||||
tx.PayloadHash = externalapi.DomainHash{}
|
||||
},
|
||||
ruleerrors.ErrInvalidPayloadHash},
|
||||
{"invalid payload hash in native subnetwork", 1, 1, 0,
|
||||
subnetworks.SubnetworkIDNative,
|
||||
nil,
|
||||
func(tx *externalapi.DomainTransaction) {
|
||||
tx.PayloadHash = *hashes.PayloadHash(tx.Payload)
|
||||
},
|
||||
ruleerrors.ErrInvalidPayloadHash},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
@@ -14,7 +14,6 @@ type transactionValidator struct {
|
||||
databaseContext model.DBReader
|
||||
pastMedianTimeManager model.PastMedianTimeManager
|
||||
ghostdagDataStore model.GHOSTDAGDataStore
|
||||
daaBlocksStore model.DAABlocksStore
|
||||
enableNonNativeSubnetworks bool
|
||||
massPerTxByte uint64
|
||||
massPerScriptPubKeyByte uint64
|
||||
@@ -32,9 +31,7 @@ func New(blockCoinbaseMaturity uint64,
|
||||
maxCoinbasePayloadLength uint64,
|
||||
databaseContext model.DBReader,
|
||||
pastMedianTimeManager model.PastMedianTimeManager,
|
||||
ghostdagDataStore model.GHOSTDAGDataStore,
|
||||
daaBlocksStore model.DAABlocksStore) model.TransactionValidator {
|
||||
|
||||
ghostdagDataStore model.GHOSTDAGDataStore) model.TransactionValidator {
|
||||
return &transactionValidator{
|
||||
blockCoinbaseMaturity: blockCoinbaseMaturity,
|
||||
enableNonNativeSubnetworks: enableNonNativeSubnetworks,
|
||||
@@ -45,7 +42,6 @@ func New(blockCoinbaseMaturity uint64,
|
||||
databaseContext: databaseContext,
|
||||
pastMedianTimeManager: pastMedianTimeManager,
|
||||
ghostdagDataStore: ghostdagDataStore,
|
||||
daaBlocksStore: daaBlocksStore,
|
||||
sigCache: txscript.NewSigCache(sigCacheSize),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@ import (
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/domain/consensus"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
|
||||
"math/big"
|
||||
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
@@ -35,7 +36,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
|
||||
factory := consensus.NewFactory()
|
||||
pastMedianManager := &mocPastMedianTimeManager{}
|
||||
factory.SetTestPastMedianTimeManager(func(int, model.DBReader, model.DAGTraversalManager, model.BlockHeaderStore,
|
||||
model.GHOSTDAGDataStore, *externalapi.DomainHash) model.PastMedianTimeManager {
|
||||
model.GHOSTDAGDataStore) model.PastMedianTimeManager {
|
||||
return pastMedianManager
|
||||
})
|
||||
tc, tearDown, err := factory.NewTestConsensus(params, false,
|
||||
@@ -116,16 +117,6 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
|
||||
SubnetworkID: subnetworks.SubnetworkIDRegistry,
|
||||
Gas: 0,
|
||||
LockTime: 0}
|
||||
|
||||
for i, input := range validTx.Inputs {
|
||||
signatureScript, err := txscript.SignatureScript(&validTx, i, consensushashing.SigHashAll, privateKey,
|
||||
&consensushashing.SighashReusedValues{})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a sigScript: %v", err)
|
||||
}
|
||||
input.SignatureScript = signatureScript
|
||||
}
|
||||
|
||||
txWithImmatureCoinbase := externalapi.DomainTransaction{
|
||||
Version: constants.MaxTransactionVersion,
|
||||
Inputs: []*externalapi.DomainTransactionInput{&txInput},
|
||||
@@ -155,9 +146,30 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
|
||||
Gas: 0,
|
||||
LockTime: 0}
|
||||
|
||||
for i, input := range validTx.Inputs {
|
||||
signatureScript, err := txscript.SignatureScript(&validTx, i, scriptPublicKey, txscript.SigHashAll, privateKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a sigScript: %v", err)
|
||||
}
|
||||
input.SignatureScript = signatureScript
|
||||
}
|
||||
|
||||
povBlockHash := externalapi.NewDomainHashFromByteArray(&[32]byte{0x01})
|
||||
tc.DAABlocksStore().StageDAAScore(povBlockHash, params.BlockCoinbaseMaturity+txInput.UTXOEntry.BlockDAAScore())
|
||||
tc.DAABlocksStore().StageDAAScore(povBlockHash, 10)
|
||||
genesisHash := params.GenesisHash
|
||||
tc.GHOSTDAGDataStore().Stage(model.VirtualBlockHash, model.NewBlockGHOSTDAGData(
|
||||
params.BlockCoinbaseMaturity+txInput.UTXOEntry.BlockBlueScore(),
|
||||
new(big.Int),
|
||||
genesisHash,
|
||||
make([]*externalapi.DomainHash, 1000),
|
||||
make([]*externalapi.DomainHash, 1),
|
||||
nil))
|
||||
tc.GHOSTDAGDataStore().Stage(povBlockHash, model.NewBlockGHOSTDAGData(
|
||||
10,
|
||||
new(big.Int),
|
||||
genesisHash,
|
||||
make([]*externalapi.DomainHash, 1000),
|
||||
make([]*externalapi.DomainHash, 1),
|
||||
nil))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -176,7 +188,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
|
||||
expectedError: nil,
|
||||
},
|
||||
{ // The calculated block coinbase maturity is smaller than the minimum expected blockCoinbaseMaturity.
|
||||
// The povBlockHash DAA score is 10 and the UTXO DAA score is 5, hence the The subtraction between
|
||||
// The povBlockHash blue score is 10 and the UTXO blue score is 5, hence the The subtraction between
|
||||
// them will yield a smaller result than the required CoinbaseMaturity (currently set to 100).
|
||||
name: "checkTransactionCoinbaseMaturity",
|
||||
tx: &txWithImmatureCoinbase,
|
||||
@@ -226,12 +238,12 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
|
||||
if test.isValid {
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error on TestValidateTransactionInContextAndPopulateMassAndFee"+
|
||||
" on test '%v': %v", test.name, err)
|
||||
" on test %v: %v", test.name, err)
|
||||
}
|
||||
} else {
|
||||
if err == nil || !errors.Is(err, test.expectedError) {
|
||||
t.Fatalf("TestValidateTransactionInContextAndPopulateMassAndFee: test %v:"+
|
||||
" Unexpected error: Expected to: %v, but got : %+v", test.name, test.expectedError, err)
|
||||
" Unexpected error: Expected to: %v, but got : %v", test.name, test.expectedError, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +139,9 @@ var (
|
||||
// a Payload
|
||||
ErrInvalidPayload = newRuleError("ErrInvalidPayload")
|
||||
|
||||
// ErrInvalidPayloadHash invalid hash of transaction's payload
|
||||
ErrInvalidPayloadHash = newRuleError("ErrInvalidPayloadHash")
|
||||
|
||||
// ErrSubnetwork indicates that a block doesn't adhere to the subnetwork
|
||||
// registry rules
|
||||
ErrSubnetworkRegistry = newRuleError("ErrSubnetworkRegistry")
|
||||
|
||||
@@ -2,8 +2,6 @@ package ruleerrors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
@@ -47,11 +45,9 @@ func TestNewErrMissingTxOut(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewErrInvalidTransactionsInNewBlock(t *testing.T) {
|
||||
tx := &externalapi.DomainTransaction{Fee: 1337}
|
||||
txID := consensushashing.TransactionID(tx)
|
||||
outer := NewErrInvalidTransactionsInNewBlock([]InvalidTransaction{{tx, ErrNoTxInputs}})
|
||||
outer := NewErrInvalidTransactionsInNewBlock([]InvalidTransaction{{&externalapi.DomainTransaction{Fee: 1337}, ErrNoTxInputs}})
|
||||
//TODO: Implement Stringer for `DomainTransaction`
|
||||
expectedOuterErr := fmt.Sprintf("ErrInvalidTransactionsInNewBlock: [(%s: ErrNoTxInputs)]", txID)
|
||||
expectedOuterErr := "ErrInvalidTransactionsInNewBlock: [(bbf6e84f5a6333948063aa45ea02ff5bb0355e11e41becf20245791f61179db1: ErrNoTxInputs)]"
|
||||
inner := &ErrInvalidTransactionsInNewBlock{}
|
||||
if !errors.As(outer, inner) {
|
||||
t.Fatal("TestNewErrInvalidTransactionsInNewBlock: Outer should contain ErrInvalidTransactionsInNewBlock in it")
|
||||
|
||||
@@ -137,7 +137,3 @@ func (tc *testConsensus) FinalityStore() model.FinalityStore {
|
||||
func (tc *testConsensus) HeadersSelectedChainStore() model.HeadersSelectedChainStore {
|
||||
return tc.headersSelectedChainStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) DAABlocksStore() model.DAABlocksStore {
|
||||
return tc.daaBlocksStore
|
||||
}
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
package consensushashing
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/serialization"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SigHashType represents hash type bits at the end of a signature.
|
||||
type SigHashType uint8
|
||||
|
||||
// Hash type bits from the end of a signature.
|
||||
const (
|
||||
SigHashAll SigHashType = 0b00000001
|
||||
SigHashNone SigHashType = 0b00000010
|
||||
SigHashSingle SigHashType = 0b00000100
|
||||
SigHashAnyOneCanPay SigHashType = 0b10000000
|
||||
|
||||
// SigHashMask defines the number of bits of the hash type which is used
|
||||
// to identify which outputs are signed.
|
||||
SigHashMask = 0b00000111
|
||||
)
|
||||
|
||||
// IsStandardSigHashType returns true if sht represents a standard SigHashType
|
||||
func (sht SigHashType) IsStandardSigHashType() bool {
|
||||
switch sht {
|
||||
case SigHashAll, SigHashNone, SigHashSingle,
|
||||
SigHashAll | SigHashAnyOneCanPay, SigHashNone | SigHashAnyOneCanPay, SigHashSingle | SigHashAnyOneCanPay:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (sht SigHashType) isSigHashAll() bool {
|
||||
return sht&SigHashMask == SigHashAll
|
||||
}
|
||||
func (sht SigHashType) isSigHashNone() bool {
|
||||
return sht&SigHashMask == SigHashNone
|
||||
}
|
||||
func (sht SigHashType) isSigHashSingle() bool {
|
||||
return sht&SigHashMask == SigHashSingle
|
||||
}
|
||||
func (sht SigHashType) isSigHashAnyOneCanPay() bool {
|
||||
return sht&SigHashAnyOneCanPay == SigHashAnyOneCanPay
|
||||
}
|
||||
|
||||
// SighashReusedValues holds all fields used in the calculation of a transaction's sigHash, that are
|
||||
// the same for all transaction inputs.
|
||||
// Reuse of such values prevents the quadratic hashing problem.
|
||||
type SighashReusedValues struct {
|
||||
previousOutputsHash *externalapi.DomainHash
|
||||
sequencesHash *externalapi.DomainHash
|
||||
outputsHash *externalapi.DomainHash
|
||||
payloadHash *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// CalculateSignatureHash will, given a script and hash type calculate the signature hash
|
||||
// to be used for signing and verification.
|
||||
// This returns error only if one of the provided parameters are consensus-invalid.
|
||||
func CalculateSignatureHash(tx *externalapi.DomainTransaction, inputIndex int, hashType SigHashType,
|
||||
reusedValues *SighashReusedValues) (*externalapi.DomainHash, error) {
|
||||
|
||||
if !hashType.IsStandardSigHashType() {
|
||||
return nil, errors.Errorf("SigHashType %d is not a valid SigHash type", hashType)
|
||||
}
|
||||
|
||||
txIn := tx.Inputs[inputIndex]
|
||||
prevScriptPublicKey := txIn.UTXOEntry.ScriptPublicKey()
|
||||
|
||||
if tx.Version > constants.MaxTransactionVersion {
|
||||
return nil, errors.Errorf("Transaction version is unknown.")
|
||||
}
|
||||
|
||||
if prevScriptPublicKey.Version > constants.MaxScriptPublicKeyVersion {
|
||||
return nil, errors.Errorf("Script version is unknown.")
|
||||
}
|
||||
|
||||
return calculateSignatureHash(tx, inputIndex, txIn, prevScriptPublicKey, hashType, reusedValues)
|
||||
}
|
||||
|
||||
func calculateSignatureHash(tx *externalapi.DomainTransaction, inputIndex int, txIn *externalapi.DomainTransactionInput,
|
||||
prevScriptPublicKey *externalapi.ScriptPublicKey, hashType SigHashType, reusedValues *SighashReusedValues) (
|
||||
*externalapi.DomainHash, error) {
|
||||
|
||||
hashWriter := hashes.NewTransactionSigningHashWriter()
|
||||
infallibleWriteElement(hashWriter, tx.Version)
|
||||
|
||||
previousOutputsHash := getPreviousOutputsHash(tx, hashType, reusedValues)
|
||||
infallibleWriteElement(hashWriter, previousOutputsHash)
|
||||
|
||||
sequencesHash := getSequencesHash(tx, hashType, reusedValues)
|
||||
infallibleWriteElement(hashWriter, sequencesHash)
|
||||
|
||||
hashOutpoint(hashWriter, txIn.PreviousOutpoint)
|
||||
|
||||
infallibleWriteElement(hashWriter, prevScriptPublicKey.Version)
|
||||
infallibleWriteElement(hashWriter, prevScriptPublicKey.Script)
|
||||
|
||||
infallibleWriteElement(hashWriter, txIn.UTXOEntry.Amount())
|
||||
|
||||
infallibleWriteElement(hashWriter, txIn.Sequence)
|
||||
|
||||
outputsHash := getOutputsHash(tx, inputIndex, hashType, reusedValues)
|
||||
infallibleWriteElement(hashWriter, outputsHash)
|
||||
|
||||
infallibleWriteElement(hashWriter, tx.LockTime)
|
||||
|
||||
infallibleWriteElement(hashWriter, tx.SubnetworkID)
|
||||
infallibleWriteElement(hashWriter, tx.Gas)
|
||||
|
||||
payloadHash := getPayloadHash(tx, reusedValues)
|
||||
infallibleWriteElement(hashWriter, payloadHash)
|
||||
|
||||
infallibleWriteElement(hashWriter, uint8(hashType))
|
||||
|
||||
return hashWriter.Finalize(), nil
|
||||
}
|
||||
|
||||
func getPreviousOutputsHash(tx *externalapi.DomainTransaction, hashType SigHashType, reusedValues *SighashReusedValues) *externalapi.DomainHash {
|
||||
if hashType.isSigHashAnyOneCanPay() {
|
||||
return externalapi.NewZeroHash()
|
||||
}
|
||||
|
||||
if reusedValues.previousOutputsHash == nil {
|
||||
hashWriter := hashes.NewTransactionSigningHashWriter()
|
||||
for _, txIn := range tx.Inputs {
|
||||
hashOutpoint(hashWriter, txIn.PreviousOutpoint)
|
||||
}
|
||||
reusedValues.previousOutputsHash = hashWriter.Finalize()
|
||||
}
|
||||
|
||||
return reusedValues.previousOutputsHash
|
||||
}
|
||||
|
||||
func getSequencesHash(tx *externalapi.DomainTransaction, hashType SigHashType, reusedValues *SighashReusedValues) *externalapi.DomainHash {
|
||||
if hashType.isSigHashSingle() || hashType.isSigHashAnyOneCanPay() || hashType.isSigHashNone() {
|
||||
return externalapi.NewZeroHash()
|
||||
}
|
||||
|
||||
if reusedValues.sequencesHash == nil {
|
||||
hashWriter := hashes.NewTransactionSigningHashWriter()
|
||||
for _, txIn := range tx.Inputs {
|
||||
infallibleWriteElement(hashWriter, txIn.Sequence)
|
||||
}
|
||||
reusedValues.sequencesHash = hashWriter.Finalize()
|
||||
}
|
||||
|
||||
return reusedValues.sequencesHash
|
||||
}
|
||||
|
||||
func getOutputsHash(tx *externalapi.DomainTransaction, inputIndex int, hashType SigHashType, reusedValues *SighashReusedValues) *externalapi.DomainHash {
|
||||
// SigHashNone: return zero-hash
|
||||
if hashType.isSigHashNone() {
|
||||
return externalapi.NewZeroHash()
|
||||
}
|
||||
|
||||
// SigHashSingle: If the relevant output exists - return it's hash, otherwise return zero-hash
|
||||
if hashType.isSigHashSingle() {
|
||||
if inputIndex >= len(tx.Outputs) {
|
||||
return externalapi.NewZeroHash()
|
||||
}
|
||||
hashWriter := hashes.NewTransactionSigningHashWriter()
|
||||
hashTxOut(hashWriter, tx.Outputs[inputIndex])
|
||||
return hashWriter.Finalize()
|
||||
}
|
||||
|
||||
// SigHashAll: Return hash of all outputs. Re-use hash if available.
|
||||
if reusedValues.outputsHash == nil {
|
||||
hashWriter := hashes.NewTransactionSigningHashWriter()
|
||||
for _, txOut := range tx.Outputs {
|
||||
hashTxOut(hashWriter, txOut)
|
||||
}
|
||||
reusedValues.outputsHash = hashWriter.Finalize()
|
||||
}
|
||||
|
||||
return reusedValues.outputsHash
|
||||
}
|
||||
|
||||
func getPayloadHash(tx *externalapi.DomainTransaction, reusedValues *SighashReusedValues) *externalapi.DomainHash {
|
||||
if tx.SubnetworkID.Equal(&subnetworks.SubnetworkIDNative) {
|
||||
return externalapi.NewZeroHash()
|
||||
}
|
||||
|
||||
if reusedValues.payloadHash == nil {
|
||||
hashWriter := hashes.NewTransactionSigningHashWriter()
|
||||
infallibleWriteElement(hashWriter, tx.Payload)
|
||||
reusedValues.payloadHash = hashWriter.Finalize()
|
||||
}
|
||||
return reusedValues.payloadHash
|
||||
}
|
||||
|
||||
func hashTxOut(hashWriter hashes.HashWriter, txOut *externalapi.DomainTransactionOutput) {
|
||||
infallibleWriteElement(hashWriter, txOut.Value)
|
||||
infallibleWriteElement(hashWriter, txOut.ScriptPublicKey.Version)
|
||||
infallibleWriteElement(hashWriter, txOut.ScriptPublicKey.Script)
|
||||
}
|
||||
|
||||
func hashOutpoint(hashWriter hashes.HashWriter, outpoint externalapi.DomainOutpoint) {
|
||||
infallibleWriteElement(hashWriter, outpoint.TransactionID)
|
||||
infallibleWriteElement(hashWriter, outpoint.Index)
|
||||
}
|
||||
|
||||
func infallibleWriteElement(hashWriter hashes.HashWriter, element interface{}) {
|
||||
err := serialization.WriteElement(hashWriter, element)
|
||||
if err != nil {
|
||||
// It seems like this could only happen if the writer returned an error.
|
||||
// and this writer should never return an error (no allocations or possible failures)
|
||||
// the only non-writer error path here is unknown types in `WriteElement`
|
||||
panic(errors.Wrap(err, "TransactionHashForSigning() failed. this should never fail for structurally-valid transactions"))
|
||||
}
|
||||
}
|
||||
@@ -1,394 +0,0 @@
|
||||
package consensushashing_test
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// shortened versions of SigHash types to fit in single line of test case
|
||||
const (
|
||||
all = consensushashing.SigHashAll
|
||||
none = consensushashing.SigHashNone
|
||||
single = consensushashing.SigHashSingle
|
||||
allAnyoneCanPay = consensushashing.SigHashAll | consensushashing.SigHashAnyOneCanPay
|
||||
noneAnyoneCanPay = consensushashing.SigHashNone | consensushashing.SigHashAnyOneCanPay
|
||||
singleAnyoneCanPay = consensushashing.SigHashSingle | consensushashing.SigHashAnyOneCanPay
|
||||
)
|
||||
|
||||
func modifyOutput(outputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
clone.Outputs[outputIndex].Value = 100
|
||||
return clone
|
||||
}
|
||||
}
|
||||
|
||||
func modifyInput(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
clone.Inputs[inputIndex].PreviousOutpoint.Index = 2
|
||||
return clone
|
||||
}
|
||||
}
|
||||
|
||||
func modifyAmountSpent(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
utxoEntry := clone.Inputs[inputIndex].UTXOEntry
|
||||
clone.Inputs[inputIndex].UTXOEntry = utxo.NewUTXOEntry(666, utxoEntry.ScriptPublicKey(), false, 100)
|
||||
return clone
|
||||
}
|
||||
}
|
||||
|
||||
func modifyScriptPublicKey(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
utxoEntry := clone.Inputs[inputIndex].UTXOEntry
|
||||
scriptPublicKey := utxoEntry.ScriptPublicKey()
|
||||
scriptPublicKey.Script = append(scriptPublicKey.Script, 1, 2, 3)
|
||||
clone.Inputs[inputIndex].UTXOEntry = utxo.NewUTXOEntry(utxoEntry.Amount(), scriptPublicKey, false, 100)
|
||||
return clone
|
||||
}
|
||||
}
|
||||
|
||||
func modifySequence(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
clone.Inputs[inputIndex].Sequence = 12345
|
||||
return clone
|
||||
}
|
||||
}
|
||||
|
||||
func modifyPayload(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
clone.Payload = []byte{6, 6, 6, 4, 2, 0, 1, 3, 3, 7}
|
||||
return clone
|
||||
}
|
||||
|
||||
func modifyGas(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
clone.Gas = 1234
|
||||
return clone
|
||||
}
|
||||
|
||||
func modifySubnetworkID(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
|
||||
clone := tx.Clone()
|
||||
clone.SubnetworkID = externalapi.DomainSubnetworkID{6, 6, 6, 4, 2, 0, 1, 3, 3, 7}
|
||||
return clone
|
||||
}
|
||||
|
||||
func TestCalculateSignatureHash(t *testing.T) {
|
||||
nativeTx, subnetworkTx, err := generateTxs()
|
||||
if err != nil {
|
||||
t.Fatalf("Error from generateTxs: %+v", err)
|
||||
}
|
||||
|
||||
// Note: Expected values were generated by the same code that they test,
|
||||
// As long as those were not verified using 3rd-party code they only check for regression, not correctness
|
||||
tests := []struct {
|
||||
name string
|
||||
tx *externalapi.DomainTransaction
|
||||
hashType consensushashing.SigHashType
|
||||
inputIndex int
|
||||
modificationFunction func(*externalapi.DomainTransaction) *externalapi.DomainTransaction
|
||||
expectedSignatureHash string
|
||||
}{
|
||||
// native transactions
|
||||
|
||||
// sigHashAll
|
||||
{name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0,
|
||||
expectedSignatureHash: "c899a5ea7414f0bbfd77e50674f46da34ce8722b928d4362a4b4b727c69c6499"},
|
||||
{name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0,
|
||||
modificationFunction: modifyInput(1), // should change the hash
|
||||
expectedSignatureHash: "faf3b9db2e07b1c14b2df02002d3e40f1e430f177ac5cd3354c84dad8fbe72ce"},
|
||||
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
|
||||
modificationFunction: modifyOutput(1), // should change the hash
|
||||
expectedSignatureHash: "3a557c5b873aab72dcb81649642e1d7a63b75dcdcc74e19d340964a9e0eac76c"},
|
||||
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
|
||||
modificationFunction: modifySequence(1), // should change the hash
|
||||
expectedSignatureHash: "2dd5fe8f9fa4bf551ea2f080a26e07b2462083e12d3b2ed01cb9369a61920665"},
|
||||
{name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
|
||||
expectedSignatureHash: "19fe2e0db681017f318fda705a39bbbad9c1085514cfbcff6fac01e1725f758b"},
|
||||
{name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
|
||||
modificationFunction: modifyInput(0), // should change the hash
|
||||
expectedSignatureHash: "5b21d492560a1c794595f769b3ae3c151775b9cfc4029d17c53f1856e1005da4"},
|
||||
{name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
|
||||
modificationFunction: modifyInput(1), // shouldn't change the hash
|
||||
expectedSignatureHash: "19fe2e0db681017f318fda705a39bbbad9c1085514cfbcff6fac01e1725f758b"},
|
||||
{name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
|
||||
modificationFunction: modifySequence(1), // shouldn't change the hash
|
||||
expectedSignatureHash: "19fe2e0db681017f318fda705a39bbbad9c1085514cfbcff6fac01e1725f758b"},
|
||||
|
||||
// sigHashNone
|
||||
{name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0,
|
||||
expectedSignatureHash: "fafabaabf6349fee4e18626b4eff015472f2317576a8f4bf7b0eea1df6f3e32b"},
|
||||
{name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0,
|
||||
modificationFunction: modifyOutput(1), // shouldn't change the hash
|
||||
expectedSignatureHash: "fafabaabf6349fee4e18626b4eff015472f2317576a8f4bf7b0eea1df6f3e32b"},
|
||||
{name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0,
|
||||
modificationFunction: modifySequence(0), // should change the hash
|
||||
expectedSignatureHash: "daee0700e0ed4ab9f50de24d83e0bfce62999474ec8ceeb537ea35980662b601"},
|
||||
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
|
||||
modificationFunction: modifySequence(1), // shouldn't change the hash
|
||||
expectedSignatureHash: "fafabaabf6349fee4e18626b4eff015472f2317576a8f4bf7b0eea1df6f3e32b"},
|
||||
{name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
|
||||
expectedSignatureHash: "4e5c2d895f9711dc89c19d49ba478e9c8f4be0d82c9bd6b60d0361eb9b5296bc"},
|
||||
{name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
|
||||
modificationFunction: modifyAmountSpent(0), // should change the hash
|
||||
expectedSignatureHash: "9ce2f75eafc85b8e19133942c3143d14b61f2e7cc479fbc6d2fca026e50897f1"},
|
||||
{name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
|
||||
modificationFunction: modifyScriptPublicKey(0), // should change the hash
|
||||
expectedSignatureHash: "c6c364190520fe6c0419c2f45e25bf084356333b03ac7aaec28251126398bda3"},
|
||||
|
||||
// sigHashSingle
|
||||
{name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0,
|
||||
expectedSignatureHash: "6ff01d5d7cd82e24bc9ca0edec8bd6931ffb5aa1d303f07ca05dc89757343a92"},
|
||||
{name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0,
|
||||
modificationFunction: modifyOutput(0), // should change the hash
|
||||
expectedSignatureHash: "d62af956aea369365bacc7e7f1aac106836994f1648311e82dd38da822c8771e"},
|
||||
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
|
||||
modificationFunction: modifyOutput(1), // shouldn't change the hash
|
||||
expectedSignatureHash: "6ff01d5d7cd82e24bc9ca0edec8bd6931ffb5aa1d303f07ca05dc89757343a92"},
|
||||
{name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0,
|
||||
modificationFunction: modifySequence(0), // should change the hash
|
||||
expectedSignatureHash: "46692229d45bf2ceacb18960faba29753e325c0ade26ecf94495b91daacb828d"},
|
||||
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
|
||||
modificationFunction: modifySequence(1), // shouldn't change the hash
|
||||
expectedSignatureHash: "6ff01d5d7cd82e24bc9ca0edec8bd6931ffb5aa1d303f07ca05dc89757343a92"},
|
||||
{name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2,
|
||||
expectedSignatureHash: "d3cc385082a7f272ec2c8aae7f3a96ab2f49a4a4e1ed44d61af34058a7721281"},
|
||||
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
|
||||
modificationFunction: modifyOutput(1), // shouldn't change the hash
|
||||
expectedSignatureHash: "d3cc385082a7f272ec2c8aae7f3a96ab2f49a4a4e1ed44d61af34058a7721281"},
|
||||
{name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0,
|
||||
expectedSignatureHash: "408fcfd8ceca135c0f54569ccf8ac727e1aa6b5a15f87ccca765f1d5808aa4ea"},
|
||||
{name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2,
|
||||
expectedSignatureHash: "685fac0d0b9dd3c5556f266714c4f7f93475d49fa12befb18e8297bc062aeaba"},
|
||||
|
||||
// subnetwork transaction
|
||||
{name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0,
|
||||
expectedSignatureHash: "0e8b1433b761a220a61c0dc1f0fda909d49cef120d98d9f87344fef52dac0d8b"},
|
||||
{name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0,
|
||||
modificationFunction: modifyPayload, // should change the hash
|
||||
expectedSignatureHash: "087315acb9193eaa14929dbe3d0ace80238aebe13eab3bf8db6c0a0d7ddb782e"},
|
||||
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
|
||||
modificationFunction: modifyGas, // should change the hash
|
||||
expectedSignatureHash: "07a90408ef45864ae8354b07a74cf826a4621391425ba417470a6e680af4ce70"},
|
||||
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
|
||||
modificationFunction: modifySubnetworkID, // should change the hash
|
||||
expectedSignatureHash: "4ca44c2e35729ae5efe831a77027f1a58a41dbdd853459c26cbfe7d6c88783fb"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
tx := test.tx
|
||||
if test.modificationFunction != nil {
|
||||
tx = test.modificationFunction(tx)
|
||||
}
|
||||
|
||||
actualSignatureHash, err := consensushashing.CalculateSignatureHash(
|
||||
tx, test.inputIndex, test.hashType, &consensushashing.SighashReusedValues{})
|
||||
if err != nil {
|
||||
t.Errorf("%s: Error from CalculateSignatureHash: %+v", test.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if actualSignatureHash.String() != test.expectedSignatureHash {
|
||||
t.Errorf("%s: expected signature hash: '%s'; but got: '%s'",
|
||||
test.name, test.expectedSignatureHash, actualSignatureHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateTxs() (nativeTx, subnetworkTx *externalapi.DomainTransaction, err error) {
|
||||
genesisCoinbase := dagconfig.SimnetParams.GenesisBlock.Transactions[0]
|
||||
genesisCoinbaseTransactionID := consensushashing.TransactionID(genesisCoinbase)
|
||||
|
||||
address1Str := "kaspasim:qzpj2cfa9m40w9m2cmr8pvfuqpp32mzzwsuw6ukhfduqpp32mzzws59e8fapc"
|
||||
address1, err := util.DecodeAddress(address1Str, util.Bech32PrefixKaspaSim)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding address1: %+v", err)
|
||||
}
|
||||
address1ToScript, err := txscript.PayToAddrScript(address1)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error generating script: %+v", err)
|
||||
}
|
||||
|
||||
address2Str := "kaspasim:qr7w7nqsdnc3zddm6u8s9fex4ysk95hm3v30q353ymuqpp32mzzws59e8fapc"
|
||||
address2, err := util.DecodeAddress(address2Str, util.Bech32PrefixKaspaSim)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding address2: %+v", err)
|
||||
}
|
||||
address2ToScript, err := txscript.PayToAddrScript(address2)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error generating script: %+v", err)
|
||||
}
|
||||
|
||||
txIns := []*externalapi.DomainTransactionInput{
|
||||
{
|
||||
PreviousOutpoint: *externalapi.NewDomainOutpoint(genesisCoinbaseTransactionID, 0),
|
||||
Sequence: 0,
|
||||
UTXOEntry: utxo.NewUTXOEntry(100, address1ToScript, false, 0),
|
||||
},
|
||||
{
|
||||
PreviousOutpoint: *externalapi.NewDomainOutpoint(genesisCoinbaseTransactionID, 1),
|
||||
Sequence: 1,
|
||||
UTXOEntry: utxo.NewUTXOEntry(200, address2ToScript, false, 0),
|
||||
},
|
||||
{
|
||||
PreviousOutpoint: *externalapi.NewDomainOutpoint(genesisCoinbaseTransactionID, 2),
|
||||
Sequence: 2,
|
||||
UTXOEntry: utxo.NewUTXOEntry(300, address2ToScript, false, 0),
|
||||
},
|
||||
}
|
||||
|
||||
txOuts := []*externalapi.DomainTransactionOutput{
|
||||
{
|
||||
Value: 300,
|
||||
ScriptPublicKey: address2ToScript,
|
||||
},
|
||||
{
|
||||
Value: 300,
|
||||
ScriptPublicKey: address1ToScript,
|
||||
},
|
||||
}
|
||||
|
||||
nativeTx = &externalapi.DomainTransaction{
|
||||
Version: 0,
|
||||
Inputs: txIns,
|
||||
Outputs: txOuts,
|
||||
LockTime: 1615462089000,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
||||
}
|
||||
subnetworkTx = &externalapi.DomainTransaction{
|
||||
Version: 0,
|
||||
Inputs: txIns,
|
||||
Outputs: txOuts,
|
||||
LockTime: 1615462089000,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
||||
Gas: 250,
|
||||
Payload: []byte{10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}
|
||||
|
||||
return nativeTx, subnetworkTx, nil
|
||||
}
|
||||
|
||||
func BenchmarkCalculateSignatureHash(b *testing.B) {
|
||||
sigHashTypes := []consensushashing.SigHashType{
|
||||
consensushashing.SigHashAll,
|
||||
consensushashing.SigHashNone,
|
||||
consensushashing.SigHashSingle,
|
||||
consensushashing.SigHashAll | consensushashing.SigHashAnyOneCanPay,
|
||||
consensushashing.SigHashNone | consensushashing.SigHashAnyOneCanPay,
|
||||
consensushashing.SigHashSingle | consensushashing.SigHashAnyOneCanPay}
|
||||
|
||||
for _, size := range []int{10, 100, 1000} {
|
||||
tx := generateTransaction(b, sigHashTypes, size)
|
||||
|
||||
b.Run(fmt.Sprintf("%d-inputs-and-outputs", size), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
reusedValues := &consensushashing.SighashReusedValues{}
|
||||
for inputIndex := range tx.Inputs {
|
||||
sigHashType := sigHashTypes[inputIndex%len(sigHashTypes)]
|
||||
_, err := consensushashing.CalculateSignatureHash(tx, inputIndex, sigHashType, reusedValues)
|
||||
if err != nil {
|
||||
b.Fatalf("Error from CalculateSignatureHash: %+v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func generateTransaction(b *testing.B, sigHashTypes []consensushashing.SigHashType, inputAndOutputSizes int) *externalapi.DomainTransaction {
|
||||
sourceScript := getSourceScript(b)
|
||||
tx := &externalapi.DomainTransaction{
|
||||
Version: 0,
|
||||
Inputs: generateInputs(inputAndOutputSizes, sourceScript),
|
||||
Outputs: generateOutputs(inputAndOutputSizes, sourceScript),
|
||||
LockTime: 123456789,
|
||||
SubnetworkID: externalapi.DomainSubnetworkID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
||||
Gas: 125,
|
||||
Payload: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1},
|
||||
Fee: 0,
|
||||
Mass: 0,
|
||||
ID: nil,
|
||||
}
|
||||
signTx(b, tx, sigHashTypes)
|
||||
return tx
|
||||
}
|
||||
|
||||
func signTx(b *testing.B, tx *externalapi.DomainTransaction, sigHashTypes []consensushashing.SigHashType) {
|
||||
sourceAddressPKStr := "a4d85b7532123e3dd34e58d7ce20895f7ca32349e29b01700bb5a3e72d2570eb"
|
||||
privateKeyBytes, err := hex.DecodeString(sourceAddressPKStr)
|
||||
if err != nil {
|
||||
b.Fatalf("Error parsing private key hex: %+v", err)
|
||||
}
|
||||
keyPair, err := secp256k1.DeserializePrivateKeyFromSlice(privateKeyBytes)
|
||||
if err != nil {
|
||||
b.Fatalf("Error deserializing private key: %+v", err)
|
||||
}
|
||||
for i, txIn := range tx.Inputs {
|
||||
signatureScript, err := txscript.SignatureScript(
|
||||
tx, i, sigHashTypes[i%len(sigHashTypes)], keyPair, &consensushashing.SighashReusedValues{})
|
||||
if err != nil {
|
||||
b.Fatalf("Error from SignatureScript: %+v", err)
|
||||
}
|
||||
txIn.SignatureScript = signatureScript
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func generateInputs(size int, sourceScript *externalapi.ScriptPublicKey) []*externalapi.DomainTransactionInput {
|
||||
inputs := make([]*externalapi.DomainTransactionInput, size)
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
inputs[i] = &externalapi.DomainTransactionInput{
|
||||
PreviousOutpoint: *externalapi.NewDomainOutpoint(
|
||||
externalapi.NewDomainTransactionIDFromByteArray(&[32]byte{12, 3, 4, 5}), 1),
|
||||
SignatureScript: nil,
|
||||
Sequence: uint64(i),
|
||||
UTXOEntry: utxo.NewUTXOEntry(uint64(i), sourceScript, false, 12),
|
||||
}
|
||||
}
|
||||
|
||||
return inputs
|
||||
}
|
||||
|
||||
func getSourceScript(b *testing.B) *externalapi.ScriptPublicKey {
|
||||
sourceAddressStr := "kaspasim:qz6f9z6l3x4v3lf9mgf0t934th4nx5kgzu663x9yjh"
|
||||
|
||||
sourceAddress, err := util.DecodeAddress(sourceAddressStr, util.Bech32PrefixKaspaSim)
|
||||
if err != nil {
|
||||
b.Fatalf("Error from DecodeAddress: %+v", err)
|
||||
}
|
||||
|
||||
sourceScript, err := txscript.PayToAddrScript(sourceAddress)
|
||||
if err != nil {
|
||||
b.Fatalf("Error from PayToAddrScript: %+v", err)
|
||||
}
|
||||
return sourceScript
|
||||
}
|
||||
|
||||
func generateOutputs(size int, script *externalapi.ScriptPublicKey) []*externalapi.DomainTransactionOutput {
|
||||
outputs := make([]*externalapi.DomainTransactionOutput, size)
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
outputs[i] = &externalapi.DomainTransactionOutput{
|
||||
Value: uint64(i),
|
||||
ScriptPublicKey: script,
|
||||
}
|
||||
}
|
||||
|
||||
return outputs
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user