@ -1,6 +1,7 @@
package block
import (
"io"
"math/big"
"unsafe"
@ -16,6 +17,30 @@ import (
// Header represents a block header in the Harmony blockchain.
type Header struct {
fields headerFields
}
// EncodeRLP encodes the header fields into RLP format.
func ( h * Header ) EncodeRLP ( w io . Writer ) error {
return rlp . Encode ( w , & h . fields )
}
// DecodeRLP decodes the given RLP decode stream into the header fields.
func ( h * Header ) DecodeRLP ( s * rlp . Stream ) error {
return s . Decode ( & h . fields )
}
// NewHeader creates a new header object.
func NewHeader ( ) * Header {
return & Header { headerFields {
Number : new ( big . Int ) ,
Time : new ( big . Int ) ,
ViewID : new ( big . Int ) ,
Epoch : new ( big . Int ) ,
} }
}
type headerFields struct {
ParentHash common . Hash ` json:"parentHash" gencodec:"required" `
Coinbase common . Address ` json:"miner" gencodec:"required" `
Root common . Hash ` json:"stateRoot" gencodec:"required" `
@ -43,6 +68,301 @@ type Header struct {
CrossLinks [ ] byte ` json:"crossLink" `
}
// ParentHash is the header hash of the parent block. For the genesis block
// which has no parent by definition, this field is zeroed out.
func ( h * Header ) ParentHash ( ) common . Hash {
return h . fields . ParentHash
}
// SetParentHash sets the parent hash field.
func ( h * Header ) SetParentHash ( newParentHash common . Hash ) {
h . fields . ParentHash = newParentHash
}
// Coinbase is the address of the node that proposed this block and all
// transactions in it.
func ( h * Header ) Coinbase ( ) common . Address {
return h . fields . Coinbase
}
// SetCoinbase sets the coinbase address field.
func ( h * Header ) SetCoinbase ( newCoinbase common . Address ) {
h . fields . Coinbase = newCoinbase
}
// Root is the state (account) trie root hash.
func ( h * Header ) Root ( ) common . Hash {
return h . fields . Root
}
// SetRoot sets the state trie root hash field.
func ( h * Header ) SetRoot ( newRoot common . Hash ) {
h . fields . Root = newRoot
}
// TxHash is the transaction trie root hash.
func ( h * Header ) TxHash ( ) common . Hash {
return h . fields . TxHash
}
// SetTxHash sets the transaction trie root hash field.
func ( h * Header ) SetTxHash ( newTxHash common . Hash ) {
h . fields . TxHash = newTxHash
}
// ReceiptHash is the same-shard transaction receipt trie hash.
func ( h * Header ) ReceiptHash ( ) common . Hash {
return h . fields . ReceiptHash
}
// SetReceiptHash sets the same-shard transaction receipt trie hash.
func ( h * Header ) SetReceiptHash ( newReceiptHash common . Hash ) {
h . fields . ReceiptHash = newReceiptHash
}
// OutgoingReceiptHash is the egress transaction receipt trie hash.
func ( h * Header ) OutgoingReceiptHash ( ) common . Hash {
return h . fields . OutgoingReceiptHash
}
// SetOutgoingReceiptHash sets the egress transaction receipt trie hash.
func ( h * Header ) SetOutgoingReceiptHash ( newOutgoingReceiptHash common . Hash ) {
h . fields . OutgoingReceiptHash = newOutgoingReceiptHash
}
// IncomingReceiptHash is the ingress transaction receipt trie hash.
func ( h * Header ) IncomingReceiptHash ( ) common . Hash {
return h . fields . IncomingReceiptHash
}
// SetIncomingReceiptHash sets the ingress transaction receipt trie hash.
func ( h * Header ) SetIncomingReceiptHash ( newIncomingReceiptHash common . Hash ) {
h . fields . IncomingReceiptHash = newIncomingReceiptHash
}
// Bloom is the Bloom filter that indexes accounts and topics logged by smart
// contract transactions (executions) in this block.
func ( h * Header ) Bloom ( ) types . Bloom {
return h . fields . Bloom
}
// SetBloom sets the smart contract log Bloom filter for this block.
func ( h * Header ) SetBloom ( newBloom types . Bloom ) {
h . fields . Bloom = newBloom
}
// Number is the block number.
//
// The returned instance is a copy; the caller may do anything with it.
func ( h * Header ) Number ( ) * big . Int {
return new ( big . Int ) . Set ( h . fields . Number )
}
// SetNumber sets the block number.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetNumber ( newNumber * big . Int ) {
h . fields . Number . Set ( newNumber )
}
// GasLimit is the gas limit for transactions in this block.
func ( h * Header ) GasLimit ( ) uint64 {
return h . fields . GasLimit
}
// SetGasLimit sets the gas limit for transactions in this block.
func ( h * Header ) SetGasLimit ( newGasLimit uint64 ) {
h . fields . GasLimit = newGasLimit
}
// GasUsed is the amount of gas used by transactions in this block.
func ( h * Header ) GasUsed ( ) uint64 {
return h . fields . GasUsed
}
// SetGasUsed sets the amount of gas used by transactions in this block.
func ( h * Header ) SetGasUsed ( newGasUsed uint64 ) {
h . fields . GasUsed = newGasUsed
}
// Time is the UNIX timestamp of this block.
//
// The returned instance is a copy; the caller may do anything with it.
func ( h * Header ) Time ( ) * big . Int {
return new ( big . Int ) . Set ( h . fields . Time )
}
// SetTime sets the UNIX timestamp of this block.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetTime ( newTime * big . Int ) {
h . fields . Time . Set ( newTime )
}
// Extra is the extra data field of this block.
//
// The returned slice is a copy; the caller may do anything with it.
func ( h * Header ) Extra ( ) [ ] byte {
return append ( h . fields . Extra [ : 0 : 0 ] , h . fields . Extra ... )
}
// SetExtra sets the extra data field of this block.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetExtra ( newExtra [ ] byte ) {
h . fields . Extra = append ( newExtra [ : 0 : 0 ] , newExtra ... )
}
// MixDigest is the mixhash.
//
// This field is a remnant from Ethereum, and Harmony does not use it and always
// zeroes it out.
func ( h * Header ) MixDigest ( ) common . Hash {
return h . fields . MixDigest
}
// SetMixDigest sets the mixhash of this block.
func ( h * Header ) SetMixDigest ( newMixDigest common . Hash ) {
h . fields . MixDigest = newMixDigest
}
// ViewID is the ID of the view in which this block was originally proposed.
//
// It normally increases by one for each subsequent block, or by more than one
// if one or more PBFT/FBFT view changes have occurred.
//
// The returned instance is a copy; the caller may do anything with it.
func ( h * Header ) ViewID ( ) * big . Int {
return new ( big . Int ) . Set ( h . fields . ViewID )
}
// SetViewID sets the view ID in which the block was originally proposed.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetViewID ( newViewID * big . Int ) {
h . fields . ViewID . Set ( newViewID )
}
// Epoch is the epoch number of this block.
//
// The returned instance is a copy; the caller may do anything with it.
func ( h * Header ) Epoch ( ) * big . Int {
return new ( big . Int ) . Set ( h . fields . Epoch )
}
// SetEpoch sets the epoch number of this block.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetEpoch ( newEpoch * big . Int ) {
h . fields . Epoch . Set ( newEpoch )
}
// ShardID is the shard ID to which this block belongs.
func ( h * Header ) ShardID ( ) uint32 {
return h . fields . ShardID
}
// SetShardID sets the shard ID to which this block belongs.
func ( h * Header ) SetShardID ( newShardID uint32 ) {
h . fields . ShardID = newShardID
}
// LastCommitSignature is the FBFT commit group signature for the last block.
func ( h * Header ) LastCommitSignature ( ) [ 96 ] byte {
return h . fields . LastCommitSignature
}
// SetLastCommitSignature sets the FBFT commit group signature for the last
// block.
func ( h * Header ) SetLastCommitSignature ( newLastCommitSignature [ 96 ] byte ) {
h . fields . LastCommitSignature = newLastCommitSignature
}
// LastCommitBitmap is the signatory bitmap of the previous block. Bit
// positions index into committee member array.
//
// The returned slice is a copy; the caller may do anything with it.
func ( h * Header ) LastCommitBitmap ( ) [ ] byte {
return append ( h . fields . LastCommitBitmap [ : 0 : 0 ] , h . fields . LastCommitBitmap ... )
}
// SetLastCommitBitmap sets the signatory bitmap of the previous block.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetLastCommitBitmap ( newLastCommitBitmap [ ] byte ) {
h . fields . LastCommitBitmap = append ( newLastCommitBitmap [ : 0 : 0 ] , newLastCommitBitmap ... )
}
// ShardStateHash is the shard state hash.
func ( h * Header ) ShardStateHash ( ) common . Hash {
return h . fields . ShardStateHash
}
// SetShardStateHash sets the shard state hash.
func ( h * Header ) SetShardStateHash ( newShardStateHash common . Hash ) {
h . fields . ShardStateHash = newShardStateHash
}
// Vrf is the output of the VRF for the epoch.
//
// The returned slice is a copy; the caller may do anything with it.
func ( h * Header ) Vrf ( ) [ ] byte {
return append ( h . fields . Vrf [ : 0 : 0 ] , h . fields . Vrf ... )
}
// SetVrf sets the output of the VRF for the epoch.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetVrf ( newVrf [ ] byte ) {
h . fields . Vrf = append ( newVrf [ : 0 : 0 ] , newVrf ... )
}
// Vdf is the output of the VDF for the epoch.
//
// The returned slice is a copy; the caller may do anything with it.
func ( h * Header ) Vdf ( ) [ ] byte {
return append ( h . fields . Vdf [ : 0 : 0 ] , h . fields . Vdf ... )
}
// SetVdf sets the output of the VDF for the epoch.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetVdf ( newVdf [ ] byte ) {
h . fields . Vdf = append ( newVdf [ : 0 : 0 ] , newVdf ... )
}
// ShardState is the RLP-encoded form of shard state (list of committees) for
// the next epoch.
//
// The returned slice is a copy; the caller may do anything with it.
func ( h * Header ) ShardState ( ) [ ] byte {
return append ( h . fields . ShardState [ : 0 : 0 ] , h . fields . ShardState ... )
}
// SetShardState sets the RLP-encoded form of shard state
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetShardState ( newShardState [ ] byte ) {
h . fields . ShardState = append ( newShardState [ : 0 : 0 ] , newShardState ... )
}
// CrossLinks is the RLP-encoded form of non-beacon block headers chosen to be
// canonical by the beacon committee. This field is present only on beacon
// chain block headers.
//
// The returned slice is a copy; the caller may do anything with it.
func ( h * Header ) CrossLinks ( ) [ ] byte {
return append ( h . fields . CrossLinks [ : 0 : 0 ] , h . fields . CrossLinks ... )
}
// SetCrossLinks sets the RLP-encoded form of non-beacon block headers chosen to
// be canonical by the beacon committee.
//
// It stores a copy; the caller may freely modify the original.
func ( h * Header ) SetCrossLinks ( newCrossLinks [ ] byte ) {
h . fields . CrossLinks = append ( newCrossLinks [ : 0 : 0 ] , newCrossLinks ... )
}
// field type overrides for gencodec
type headerMarshaling struct {
Difficulty * hexutil . Big
@ -64,7 +384,7 @@ func (h *Header) Hash() common.Hash {
// to approximate and limit the memory consumption of various caches.
func ( h * Header ) Size ( ) common . StorageSize {
// TODO: update with new fields
return common . StorageSize ( unsafe . Sizeof ( * h ) ) + common . StorageSize ( len ( h . Extra ) + ( h . Number . BitLen ( ) + h . Time . BitLen ( ) ) / 8 )
return common . StorageSize ( unsafe . Sizeof ( * h ) ) + common . StorageSize ( len ( h . Extra ( ) ) + ( h . Number ( ) . BitLen ( ) + h . Time ( ) . BitLen ( ) ) / 8 )
}
// Logger returns a sub-logger with block contexts added.
@ -72,9 +392,9 @@ func (h *Header) Logger(logger *zerolog.Logger) *zerolog.Logger {
nlogger := logger .
With ( ) .
Str ( "blockHash" , h . Hash ( ) . Hex ( ) ) .
Uint32 ( "blockShard" , h . ShardID ) .
Uint64 ( "blockEpoch" , h . Epoch . Uint64 ( ) ) .
Uint64 ( "blockNumber" , h . Number . Uint64 ( ) ) .
Uint32 ( "blockShard" , h . ShardID ( ) ) .
Uint64 ( "blockEpoch" , h . Epoch ( ) . Uint64 ( ) ) .
Uint64 ( "blockNumber" , h . Number ( ) . Uint64 ( ) ) .
Logger ( )
return & nlogger
}
@ -82,9 +402,202 @@ func (h *Header) Logger(logger *zerolog.Logger) *zerolog.Logger {
// GetShardState returns the deserialized shard state object.
func ( h * Header ) GetShardState ( ) ( shard . State , error ) {
shardState := shard . State { }
err := rlp . DecodeBytes ( h . ShardState , & shardState )
err := rlp . DecodeBytes ( h . ShardState ( ) , & shardState )
if err != nil {
return nil , err
}
return shardState , nil
}
// HeaderFieldSetter is a header field setter.
//
// See NewHeaderWith for how it is used.
type HeaderFieldSetter struct {
h * Header
}
// NewHeaderWith creates a new header and returns its field setter context.
//
// Call a chain of setters on the returned field setter, followed by a call of
// Header method. Example:
//
// header := NewHeaderWith().
// ParentHash(parent.Hash()).
// Epoch(parent.Epoch()).
// ShardID(parent.ShardID()).
// Number(new(big.Int).Add(parent.Number(), big.NewInt(1)).
// Header()
func NewHeaderWith ( ) * HeaderFieldSetter {
return ( * HeaderFieldSetter ) ( & HeaderFieldSetter { h : NewHeader ( ) } )
}
// ParentHash sets the parent hash field.
func ( s HeaderFieldSetter ) ParentHash ( newParentHash common . Hash ) HeaderFieldSetter {
s . h . SetParentHash ( newParentHash )
return s
}
// Coinbase sets the coinbase address field.
func ( s HeaderFieldSetter ) Coinbase ( newCoinbase common . Address ) HeaderFieldSetter {
s . h . SetCoinbase ( newCoinbase )
return s
}
// Root sets the state trie root hash field.
func ( s HeaderFieldSetter ) Root ( newRoot common . Hash ) HeaderFieldSetter {
s . h . SetRoot ( newRoot )
return s
}
// TxHash sets the transaction trie root hash field.
func ( s HeaderFieldSetter ) TxHash ( newTxHash common . Hash ) HeaderFieldSetter {
s . h . SetTxHash ( newTxHash )
return s
}
// ReceiptHash sets the same-shard transaction receipt trie hash.
func ( s HeaderFieldSetter ) ReceiptHash ( newReceiptHash common . Hash ) HeaderFieldSetter {
s . h . SetReceiptHash ( newReceiptHash )
return s
}
// OutgoingReceiptHash sets the egress transaction receipt trie hash.
func ( s HeaderFieldSetter ) OutgoingReceiptHash ( newOutgoingReceiptHash common . Hash ) HeaderFieldSetter {
s . h . SetOutgoingReceiptHash ( newOutgoingReceiptHash )
return s
}
// IncomingReceiptHash sets the ingress transaction receipt trie hash.
func ( s HeaderFieldSetter ) IncomingReceiptHash ( newIncomingReceiptHash common . Hash ) HeaderFieldSetter {
s . h . SetIncomingReceiptHash ( newIncomingReceiptHash )
return s
}
// Bloom sets the smart contract log Bloom filter for this block.
func ( s HeaderFieldSetter ) Bloom ( newBloom types . Bloom ) HeaderFieldSetter {
s . h . SetBloom ( newBloom )
return s
}
// Number sets the block number.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) Number ( newNumber * big . Int ) HeaderFieldSetter {
s . h . SetNumber ( newNumber )
return s
}
// GasLimit sets the gas limit for transactions in this block.
func ( s HeaderFieldSetter ) GasLimit ( newGasLimit uint64 ) HeaderFieldSetter {
s . h . SetGasLimit ( newGasLimit )
return s
}
// GasUsed sets the amount of gas used by transactions in this block.
func ( s HeaderFieldSetter ) GasUsed ( newGasUsed uint64 ) HeaderFieldSetter {
s . h . SetGasUsed ( newGasUsed )
return s
}
// Time sets the UNIX timestamp of this block.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) Time ( newTime * big . Int ) HeaderFieldSetter {
s . h . SetTime ( newTime )
return s
}
// Extra sets the extra data field of this block.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) Extra ( newExtra [ ] byte ) HeaderFieldSetter {
s . h . SetExtra ( newExtra )
return s
}
// MixDigest sets the mixhash of this block.
func ( s HeaderFieldSetter ) MixDigest ( newMixDigest common . Hash ) HeaderFieldSetter {
s . h . SetMixDigest ( newMixDigest )
return s
}
// ViewID sets the view ID in which the block was originally proposed.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) ViewID ( newViewID * big . Int ) HeaderFieldSetter {
s . h . SetViewID ( newViewID )
return s
}
// Epoch sets the epoch number of this block.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) Epoch ( newEpoch * big . Int ) HeaderFieldSetter {
s . h . SetEpoch ( newEpoch )
return s
}
// ShardID sets the shard ID to which this block belongs.
func ( s HeaderFieldSetter ) ShardID ( newShardID uint32 ) HeaderFieldSetter {
s . h . SetShardID ( newShardID )
return s
}
// LastCommitSignature sets the FBFT commit group signature for the last block.
func ( s HeaderFieldSetter ) LastCommitSignature ( newLastCommitSignature [ 96 ] byte ) HeaderFieldSetter {
s . h . SetLastCommitSignature ( newLastCommitSignature )
return s
}
// LastCommitBitmap sets the signatory bitmap of the previous block.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) LastCommitBitmap ( newLastCommitBitmap [ ] byte ) HeaderFieldSetter {
s . h . SetLastCommitBitmap ( newLastCommitBitmap )
return s
}
// ShardStateHash sets the shard state hash.
func ( s HeaderFieldSetter ) ShardStateHash ( newShardStateHash common . Hash ) HeaderFieldSetter {
s . h . SetShardStateHash ( newShardStateHash )
return s
}
// Vrf sets the output of the VRF for the epoch.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) Vrf ( newVrf [ ] byte ) HeaderFieldSetter {
s . h . SetVrf ( newVrf )
return s
}
// Vdf sets the output of the VDF for the epoch.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) Vdf ( newVdf [ ] byte ) HeaderFieldSetter {
s . h . SetVdf ( newVdf )
return s
}
// ShardState sets the RLP-encoded form of shard state
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) ShardState ( newShardState [ ] byte ) HeaderFieldSetter {
s . h . SetShardState ( newShardState )
return s
}
// CrossLinks sets the RLP-encoded form of non-beacon block headers chosen to be
// canonical by the beacon committee.
//
// It stores a copy; the caller may freely modify the original.
func ( s HeaderFieldSetter ) CrossLinks ( newCrossLinks [ ] byte ) HeaderFieldSetter {
s . h . SetCrossLinks ( newCrossLinks )
return s
}
// Header returns the header whose fields have been set. Call this at the end
// of a field setter chain.
func ( s HeaderFieldSetter ) Header ( ) * Header {
return s . h
}