80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package consensus
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
|
|
"github.com/tutus-one/tutus-consensus"
|
|
"github.com/tutus-one/tutus-consensus/internal/crypto"
|
|
"github.com/tutus-one/tutus-consensus/internal/merkle"
|
|
)
|
|
|
|
type preBlock struct {
|
|
base
|
|
|
|
// A magic number CN nodes should exchange during Commit phase
|
|
// and used to construct the final list of transactions for amevBlock.
|
|
data uint32
|
|
|
|
initialTransactions []dbft.Transaction[crypto.Uint256]
|
|
}
|
|
|
|
var _ dbft.PreBlock[crypto.Uint256] = new(preBlock)
|
|
|
|
// NewPreBlock returns new preBlock.
|
|
func NewPreBlock(timestamp uint64, index uint32, prevHash crypto.Uint256, nonce uint64, txHashes []crypto.Uint256) dbft.PreBlock[crypto.Uint256] {
|
|
pre := new(preBlock)
|
|
pre.Timestamp = uint32(timestamp / 1000000000)
|
|
pre.Index = index
|
|
|
|
// NextConsensus and Version information is not provided by dBFT context,
|
|
// these are implementation-specific fields, and thus, should be managed outside the
|
|
// dBFT library. For simulation simplicity, let's assume that these fields are filled
|
|
// by every CN separately and is not verified.
|
|
pre.NextConsensus = crypto.Uint160{1, 2, 3}
|
|
pre.Version = 0
|
|
|
|
pre.PrevHash = prevHash
|
|
pre.ConsensusData = nonce
|
|
|
|
// Canary default value.
|
|
pre.data = 0xff
|
|
|
|
if len(txHashes) != 0 {
|
|
mt := merkle.NewMerkleTree(txHashes...)
|
|
pre.MerkleRoot = mt.Root().Hash
|
|
}
|
|
return pre
|
|
}
|
|
|
|
func (pre *preBlock) Data() []byte {
|
|
var res = make([]byte, 4)
|
|
binary.BigEndian.PutUint32(res, pre.data)
|
|
return res
|
|
}
|
|
|
|
func (pre *preBlock) SetData(_ dbft.PrivateKey) error {
|
|
// Just an artificial rule for data construction, it can be anything, and in Neo X
|
|
// it will be decrypted transactions fragments.
|
|
pre.data = pre.Index
|
|
return nil
|
|
}
|
|
|
|
func (pre *preBlock) Verify(_ dbft.PublicKey, data []byte) error {
|
|
if len(data) != 4 {
|
|
return errors.New("invalid data len")
|
|
}
|
|
if binary.BigEndian.Uint32(data) != pre.Index { // Just an artificial verification rule, and for NeoX it should be decrypted transactions fragments verification.
|
|
return errors.New("invalid data")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (pre *preBlock) Transactions() []dbft.Transaction[crypto.Uint256] {
|
|
return pre.initialTransactions
|
|
}
|
|
|
|
func (pre *preBlock) SetTransactions(txs []dbft.Transaction[crypto.Uint256]) {
|
|
pre.initialTransactions = txs
|
|
}
|