Version headers

block.Header is now a lightweight wrapper around an embedded
HeaderInterface value, which is implemented by both v0 and v1 headers.
It inherits all methods from the wrapped HeaderInterface, except it
overrides EncodeRLP, DecodeRLP, and Hash to handle tagged-RLP
encoding/decoding.  (block.HeaderRegistry is the tagged RLP registry for
versioned headers.)

A ripple effect is that header instance creation now requires knowledge
of epoch.  This logic is handled by blockfactory.  blockfactory.Factory
is the interface, implemented by blockfactory.factory type.  It uses a
chain config to pull in the right epoch for the right type.

As a convenience, blockfactory.NewTestHeader creates a new test-purpose
headers.  Use this in contexts where the implied chain config is
TestChainConfig or the chain config does not matter.

Miscellaneous changes:

  - block.HeaderFieldSetter now lives in its own file.

  - The functionality of block.NewHeaderWith has been replaced by the
    (*block.Header).With method.

The accompanying unit tests for (*block.Header).EncodeRLP and
(*block.Header).DecodeRLP() are the cross-sectional unit tests for the
functionality added by this.  They make sure that v0 header is
encoded/decoded without tagged RLP envelope (compatibility mode), and v1
header is encoded/decoded with one.  See comments of the RLP byte
sequence for differences.
pull/1538/head
Eugene Kim 5 years ago
parent df76865cd3
commit 8ac058bb2e
  1. 6
      api/client/service/server_test.go
  2. 5
      api/proto/node/node_test.go
  3. 6
      api/service/explorer/storage_test.go
  4. 4
      api/service/explorer/structs_test.go
  5. 49
      block/factory/factory.go
  6. 242
      block/header.go
  7. 537
      block/header_test.go
  8. 186
      block/headerfieldsetter.go
  9. 228
      block/headerif.go
  10. 24
      consensus/consensus_v2.go
  11. 13
      core/chain_makers.go
  12. 16
      core/core_test.go
  13. 30
      core/genesis.go
  14. 16
      core/rawdb/accessors_chain_test.go
  15. 4
      core/rawdb/accessors_indexes_test.go
  16. 4
      core/tx_pool_test.go
  17. 4
      core/types/block_test.go
  18. 4
      drand/drand_test.go
  19. 3
      go.mod
  20. 2
      node/node_genesis.go
  21. 16
      node/worker/worker.go
  22. 6
      node/worker/worker_test.go
  23. 5
      test/chain/main.go

@ -6,6 +6,7 @@ import (
"strings"
"testing"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/internal/chain"
"github.com/ethereum/go-ethereum/common"
@ -27,7 +28,8 @@ var (
testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
testBankFunds = big.NewInt(8000000000000000000)
chainConfig = params.TestChainConfig
chainConfig = params.TestChainConfig
blockFactory = blockfactory.NewFactory(chainConfig)
)
func TestGetFreeToken(test *testing.T) {
@ -56,6 +58,7 @@ func TestFetchAccountState(test *testing.T) {
database = ethdb.NewMemDatabase()
gspec = core.Genesis{
Config: chainConfig,
Factory: blockFactory,
Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
ShardID: 10,
}
@ -93,6 +96,7 @@ func TestGetStakingContractInfo(test *testing.T) {
database = ethdb.NewMemDatabase()
gspec = core.Genesis{
Config: chainConfig,
Factory: blockFactory,
Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
ShardID: 10,
}

@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/internal/params"
@ -60,9 +60,8 @@ func TestConstructBlocksSyncMessage(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
root := statedb.IntermediateRoot(false)
head := block.NewHeaderWith().
head := blockfactory.NewTestHeader().With().
Number(new(big.Int).SetUint64(uint64(10000))).
Epoch(big.NewInt(0)).
ShardID(0).
Time(new(big.Int).SetUint64(uint64(100000))).
Root(root).

@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/bls/ffi/go/bls"
block2 "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/shard"
@ -58,7 +58,7 @@ func TestDump(t *testing.T) {
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), 0, big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33})
txs := []*types.Transaction{tx1, tx2, tx3}
block := types.NewBlock(block2.NewHeaderWith().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
block := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
ins := GetStorageInstance("1.1.1.1", "3333", true)
ins.Dump(block, uint64(1))
db := ins.GetDB()
@ -116,7 +116,7 @@ func TestUpdateAddressStorage(t *testing.T) {
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), 0, big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33})
txs := []*types.Transaction{tx1, tx2, tx3}
block := types.NewBlock(block2.NewHeaderWith().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
block := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
ins := GetStorageInstance("1.1.1.1", "3333", true)
ins.Dump(block, uint64(1))
db := ins.GetDB()

@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
block2 "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/core/types"
)
@ -20,7 +20,7 @@ func TestGetTransaction(t *testing.T) {
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), 0, big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33})
txs := []*types.Transaction{tx1, tx2, tx3}
block := types.NewBlock(block2.NewHeaderWith().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
block := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
tx := GetTransaction(tx1, block)
assert.Equal(t, tx.ID, tx1.Hash().Hex(), "should be equal tx1.Hash()")

@ -0,0 +1,49 @@
package blockfactory
import (
"math/big"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/v0"
"github.com/harmony-one/harmony/block/v1"
"github.com/harmony-one/harmony/internal/params"
)
// Factory is a data structure factory for a specific chain configuration.
type Factory interface {
// NewHeader creates a new, empty header object for the given epoch.
NewHeader(epoch *big.Int) *block.Header
}
type factory struct {
chainConfig *params.ChainConfig
}
// NewFactory creates a new factory for the given chain configuration.
func NewFactory(chainConfig *params.ChainConfig) Factory {
return &factory{chainConfig: chainConfig}
}
func (f *factory) NewHeader(epoch *big.Int) *block.Header {
var impl block.HeaderInterface
switch {
case epoch.Cmp(f.chainConfig.CrossLinkEpoch) >= 0:
impl = v1.NewHeader()
default:
impl = v0.NewHeader()
}
return &block.Header{impl}
}
// Factories corresponding to well-known chain configurations.
var (
ForTest = NewFactory(params.TestChainConfig)
ForTestnet = NewFactory(params.TestnetChainConfig)
ForMainnet = NewFactory(params.MainnetChainConfig)
)
// NewTestHeader creates a new, empty header object for epoch 0 using the test
// factory. Use for unit tests.
func NewTestHeader() *block.Header {
return ForTest.NewHeader(new(big.Int))
}

@ -1,209 +1,83 @@
package block
import (
"math/big"
"io"
"reflect"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/taggedrlp"
"github.com/pkg/errors"
"github.com/rs/zerolog"
v0 "github.com/harmony-one/harmony/block/v0"
v1 "github.com/harmony-one/harmony/block/v1"
"github.com/harmony-one/harmony/crypto/hash"
)
// Header represents a block header in the Harmony blockchain.
type Header = v1.Header
// NewHeader creates a new header object
var NewHeader = v1.NewHeader
// 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 ethtypes.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
type Header struct {
HeaderInterface
}
// GasLimit sets the gas limit for transactions in this block.
func (s HeaderFieldSetter) GasLimit(newGasLimit uint64) HeaderFieldSetter {
s.h.SetGasLimit(newGasLimit)
return s
// EncodeRLP encodes the header using tagged RLP representation.
func (h *Header) EncodeRLP(w io.Writer) error {
return HeaderRegistry.Encode(w, h.HeaderInterface)
}
// 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
// DecodeRLP decodes the header using tagged RLP representation.
func (h *Header) DecodeRLP(s *rlp.Stream) error {
decoded, err := HeaderRegistry.Decode(s)
if err != nil {
return err
}
hif, ok := decoded.(HeaderInterface)
if !ok {
return errors.Errorf(
"decoded object (type %s) does not implement HeaderInterface",
taggedrlp.TypeName(reflect.TypeOf(decoded)))
}
h.HeaderInterface = hif
return nil
}
// 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
// Hash returns the block hash of the header. This uses HeaderRegistry to
// choose and return the right tagged RLP form of the header.
func (h *Header) Hash() ethcommon.Hash {
return hash.FromRLP(h)
}
// 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
// Logger returns a sub-logger with block contexts added.
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()).
Logger()
return &nlogger
}
// Vdf sets the output of the VDF for the epoch.
// With returns a field setter context for the header.
//
// 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
// Call a chain of setters on the returned field setter, followed by a call of
// Header method. Example:
//
// It stores a copy; the caller may freely modify the original.
func (s HeaderFieldSetter) ShardState(newShardState []byte) HeaderFieldSetter {
s.h.SetShardState(newShardState)
return s
// header := NewHeader(epoch).With().
// ParentHash(parent.Hash()).
// ShardID(parent.ShardID()).
// Number(new(big.Int).Add(parent.Number(), big.NewInt(1)).
// Header()
func (h *Header) With() HeaderFieldSetter {
return HeaderFieldSetter{h: h}
}
// 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
}
// HeaderRegistry is the taggedrlp type registry for versioned headers.
var HeaderRegistry = taggedrlp.NewRegistry()
// 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
func init() {
HeaderRegistry.MustRegister(taggedrlp.LegacyTag, v0.NewHeader())
HeaderRegistry.MustAddFactory(func() interface{} { return v0.NewHeader() })
HeaderRegistry.MustRegister("v1", v1.NewHeader())
HeaderRegistry.MustAddFactory(func() interface{} { return v1.NewHeader() })
}

@ -0,0 +1,537 @@
package block
import (
"bytes"
"reflect"
"testing"
"github.com/ethereum/go-ethereum/rlp"
v0 "github.com/harmony-one/harmony/block/v0"
v1 "github.com/harmony-one/harmony/block/v1"
)
func TestHeader_EncodeRLP(t *testing.T) {
type fields struct {
HeaderInterface HeaderInterface
}
tests := []struct {
name string
fields fields
want []byte
wantErr bool
}{
{
"v0",
fields{v0.NewHeader()},
[]byte{
// BEGIN 586-byte Header
0xf9, 0x02, 0x4a,
0xa0, // 32-byte ParentHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x94, // 20-byte Coinbase
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte Root
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte TxHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte ReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb9, 0x01, 0x00, // 256-byte Bloom
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte Number
0x80, // 0-byte GasLimit
0x80, // 0-byte GasUsed
0x80, // 0-byte Time
0x80, // 0-byte Extra
0xa0, // 32-byte MixDigest
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte ViewID
0x80, // 0-byte Epoch
0x80, // 0-byte ShardID
0xb8, 0x60, // 96-byte LastCommitSignature
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte LastCommitBitmap
0xa0, // 32-byte ShardStateHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte ShardState
// END Header
},
false,
},
{
"v1",
fields{v1.NewHeader()},
[]byte{
// BEGIN 669-byte tagged RLP envelope
0xf9, 0x02, 0x9d,
0x87, // 7-byte tagged RLP signature
'H', 'm', 'n', 'y', 'T', 'g', 'd',
0x82, // 2-byte v1 header tag
'v', '1',
// BEGIN 655-byte Header
0xf9, 0x02, 0x8f,
0xa0, // 32-byte ParentHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x94, // 20-byte Coinbase
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte Root
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte TxHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte ReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte OutgoingReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte IncomingReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb9, 0x01, 0x00, // 256-byte Bloom
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte Number
0x80, // 0-byte GasLimit
0x80, // 0-byte GasUsed
0x80, // 0-byte Time
0x80, // 0-byte Extra
0xa0, // 32-byte MixDigest
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte ViewID
0x80, // 0-byte Epoch
0x80, // 0-byte ShardID
0xb8, 0x60, // 96-byte LastCommitSignature
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte LastCommitBitmap
0xa0, // 32-byte ShardStateHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte Vrf
0x80, // 0-byte Vdf
0x80, // 0-byte ShardState
0x80, // 0-byte CrossLinks
// END Header
// END tagged RLP envelope
},
false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Header{HeaderInterface: tt.fields.HeaderInterface}
w := &bytes.Buffer{}
err := h.EncodeRLP(w)
if (err != nil) != tt.wantErr {
t.Errorf("EncodeRLP() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got := w.Bytes(); bytes.Compare(got, tt.want) != 0 {
t.Errorf("EncodeRLP() got %x", got)
t.Errorf("EncodeRLP() want %x", tt.want)
}
})
}
}
func TestHeader_DecodeRLP(t *testing.T) {
type args struct {
s *rlp.Stream
}
tests := []struct {
name string
args args
want HeaderInterface
wantErr bool
}{
{
"v0",
args{rlp.NewStream(bytes.NewBuffer([]byte{
// BEGIN 586-byte Header
0xf9, 0x02, 0x4a,
0xa0, // 32-byte ParentHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x94, // 20-byte Coinbase
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte Root
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte TxHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte ReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb9, 0x01, 0x00, // 256-byte Bloom
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte Number
0x80, // 0-byte GasLimit
0x80, // 0-byte GasUsed
0x80, // 0-byte Time
0x80, // 0-byte Extra
0xa0, // 32-byte MixDigest
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte ViewID
0x80, // 0-byte Epoch
0x80, // 0-byte ShardID
0xb8, 0x60, // 96-byte LastCommitSignature
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte LastCommitBitmap
0xa0, // 32-byte ShardStateHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte ShardState
// END Header
}), 0)},
v0.NewHeader(),
false,
},
{
"v1",
args{rlp.NewStream(bytes.NewBuffer([]byte{
// BEGIN 669-byte tagged RLP envelope
0xf9, 0x02, 0x9d,
0x87, // 7-byte tagged RLP signature
'H', 'm', 'n', 'y', 'T', 'g', 'd',
0x82, // 2-byte v1 header tag
'v', '1',
// BEGIN 655-byte Header
0xf9, 0x02, 0x8f,
0xa0, // 32-byte ParentHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x94, // 20-byte Coinbase
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte Root
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte TxHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte ReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte OutgoingReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa0, // 32-byte IncomingReceiptHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb9, 0x01, 0x00, // 256-byte Bloom
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte Number
0x80, // 0-byte GasLimit
0x80, // 0-byte GasUsed
0x80, // 0-byte Time
0x80, // 0-byte Extra
0xa0, // 32-byte MixDigest
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte ViewID
0x80, // 0-byte Epoch
0x80, // 0-byte ShardID
0xb8, 0x60, // 96-byte LastCommitSignature
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte LastCommitBitmap
0xa0, // 32-byte ShardStateHash
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, // 0-byte Vrf
0x80, // 0-byte Vdf
0x80, // 0-byte ShardState
0x80, // 0-byte CrossLinks
// END Header
// END tagged RLP envelope
}), 0)},
v1.NewHeader(),
false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Header{}
if err := h.DecodeRLP(tt.args.s); (err != nil) != tt.wantErr {
t.Errorf("DecodeRLP() error = %v, wantErr %v", err, tt.wantErr)
}
if !compareHeaders(h.HeaderInterface, tt.want) {
t.Errorf("DecodeRLP() got %#v", h.HeaderInterface)
t.Errorf("DecodeRLP() want %#v", tt.want)
}
})
}
}
func equal(x, y interface{}) bool {
xv := reflect.ValueOf(x)
yv := reflect.ValueOf(y)
if xv.Type() == yv.Type() && xv.Type().Kind() == reflect.Slice && xv.Len() == 0 && yv.Len() == 0 {
return true
}
return reflect.DeepEqual(x, y)
}
func compareHeaders(x, y HeaderInterface) bool {
return equal(x.ParentHash(), y.ParentHash()) &&
equal(x.Coinbase(), y.Coinbase()) &&
equal(x.Root(), y.Root()) &&
equal(x.TxHash(), y.TxHash()) &&
equal(x.ReceiptHash(), y.ReceiptHash()) &&
equal(x.OutgoingReceiptHash(), y.OutgoingReceiptHash()) &&
equal(x.IncomingReceiptHash(), y.IncomingReceiptHash()) &&
equal(x.Bloom(), y.Bloom()) &&
equal(x.Number(), y.Number()) &&
equal(x.GasLimit(), y.GasLimit()) &&
equal(x.GasUsed(), y.GasUsed()) &&
equal(x.Time(), y.Time()) &&
equal(x.Extra(), y.Extra()) &&
equal(x.MixDigest(), y.MixDigest()) &&
equal(x.ViewID(), y.ViewID()) &&
equal(x.Epoch(), y.Epoch()) &&
equal(x.ShardID(), y.ShardID()) &&
equal(x.LastCommitSignature(), y.LastCommitSignature()) &&
equal(x.LastCommitBitmap(), y.LastCommitBitmap()) &&
equal(x.ShardStateHash(), y.ShardStateHash()) &&
equal(x.Vrf(), y.Vrf()) &&
equal(x.Vdf(), y.Vdf()) &&
equal(x.ShardState(), y.ShardState()) &&
equal(x.CrossLinks(), y.CrossLinks())
}

@ -0,0 +1,186 @@
package block
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// HeaderFieldSetter is a header field setter.
//
// See NewHeaderWith for how it is used.
type HeaderFieldSetter struct {
h *Header
}
// 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
}

@ -0,0 +1,228 @@
package block
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/rs/zerolog"
"github.com/harmony-one/harmony/shard"
)
// HeaderInterface defines the block header interface.
type HeaderInterface interface {
// ParentHash is the header hash of the parent block. For the genesis block
// which has no parent by definition, this field is zeroed out.
ParentHash() common.Hash
// SetParentHash sets the parent hash field.
SetParentHash(newParentHash common.Hash)
// Coinbase is the address of the node that proposed this block and all
// transactions in it.
Coinbase() common.Address
// SetCoinbase sets the coinbase address field.
SetCoinbase(newCoinbase common.Address)
// Root is the state (account) trie root hash.
Root() common.Hash
// SetRoot sets the state trie root hash field.
SetRoot(newRoot common.Hash)
// TxHash is the transaction trie root hash.
TxHash() common.Hash
// SetTxHash sets the transaction trie root hash field.
SetTxHash(newTxHash common.Hash)
// ReceiptHash is the same-shard transaction receipt trie hash.
ReceiptHash() common.Hash
// SetReceiptHash sets the same-shard transaction receipt trie hash.
SetReceiptHash(newReceiptHash common.Hash)
// OutgoingReceiptHash is the egress transaction receipt trie hash.
OutgoingReceiptHash() common.Hash
// SetOutgoingReceiptHash sets the egress transaction receipt trie hash.
SetOutgoingReceiptHash(newOutgoingReceiptHash common.Hash)
// IncomingReceiptHash is the ingress transaction receipt trie hash.
IncomingReceiptHash() common.Hash
// SetIncomingReceiptHash sets the ingress transaction receipt trie hash.
SetIncomingReceiptHash(newIncomingReceiptHash common.Hash)
// Bloom is the Bloom filter that indexes accounts and topics logged by smart
// contract transactions (executions) in this block.
Bloom() types.Bloom
// SetBloom sets the smart contract log Bloom filter for this block.
SetBloom(newBloom types.Bloom)
// Number is the block number.
//
// The returned instance is a copy; the caller may do anything with it.
Number() *big.Int
// SetNumber sets the block number.
//
// It stores a copy; the caller may freely modify the original.
SetNumber(newNumber *big.Int)
// GasLimit is the gas limit for transactions in this block.
GasLimit() uint64
// SetGasLimit sets the gas limit for transactions in this block.
SetGasLimit(newGasLimit uint64)
// GasUsed is the amount of gas used by transactions in this block.
GasUsed() uint64
// SetGasUsed sets the amount of gas used by transactions in this block.
SetGasUsed(newGasUsed uint64)
// Time is the UNIX timestamp of this block.
//
// The returned instance is a copy; the caller may do anything with it.
Time() *big.Int
// SetTime sets the UNIX timestamp of this block.
//
// It stores a copy; the caller may freely modify the original.
SetTime(newTime *big.Int)
// Extra is the extra data field of this block.
//
// The returned slice is a copy; the caller may do anything with it.
Extra() []byte
// SetExtra sets the extra data field of this block.
//
// It stores a copy; the caller may freely modify the original.
SetExtra(newExtra []byte)
// MixDigest is the mixhash.
//
// This field is a remnant from Ethereum, and Harmony does not use it and always
// zeroes it out.
MixDigest() common.Hash
// SetMixDigest sets the mixhash of this block.
SetMixDigest(newMixDigest common.Hash)
// 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.
ViewID() *big.Int
// SetViewID sets the view ID in which the block was originally proposed.
//
// It stores a copy; the caller may freely modify the original.
SetViewID(newViewID *big.Int)
// Epoch is the epoch number of this block.
//
// The returned instance is a copy; the caller may do anything with it.
Epoch() *big.Int
// SetEpoch sets the epoch number of this block.
//
// It stores a copy; the caller may freely modify the original.
SetEpoch(newEpoch *big.Int)
// ShardID is the shard ID to which this block belongs.
ShardID() uint32
// SetShardID sets the shard ID to which this block belongs.
SetShardID(newShardID uint32)
// LastCommitSignature is the FBFT commit group signature for the last block.
LastCommitSignature() [96]byte
// SetLastCommitSignature sets the FBFT commit group signature for the last
// block.
SetLastCommitSignature(newLastCommitSignature [96]byte)
// 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.
LastCommitBitmap() []byte
// SetLastCommitBitmap sets the signatory bitmap of the previous block.
//
// It stores a copy; the caller may freely modify the original.
SetLastCommitBitmap(newLastCommitBitmap []byte)
// ShardStateHash is the shard state hash.
ShardStateHash() common.Hash
// SetShardStateHash sets the shard state hash.
SetShardStateHash(newShardStateHash common.Hash)
// Vrf is the output of the VRF for the epoch.
//
// The returned slice is a copy; the caller may do anything with it.
Vrf() []byte
// SetVrf sets the output of the VRF for the epoch.
//
// It stores a copy; the caller may freely modify the original.
SetVrf(newVrf []byte)
// Vdf is the output of the VDF for the epoch.
//
// The returned slice is a copy; the caller may do anything with it.
Vdf() []byte
// SetVdf sets the output of the VDF for the epoch.
//
// It stores a copy; the caller may freely modify the original.
SetVdf(newVdf []byte)
// 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.
ShardState() []byte
// SetShardState sets the RLP-encoded form of shard state
//
// It stores a copy; the caller may freely modify the original.
SetShardState(newShardState []byte)
// 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.
CrossLinks() []byte
// 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.
SetCrossLinks(newCrossLinks []byte)
// Hash returns the block hash of the header, which is simply the legacy
// Keccak256 hash of its RLP encoding.
Hash() common.Hash
// Size returns the approximate memory used by all internal contents. It is
// used to approximate and limit the memory consumption of various caches.
Size() common.StorageSize
// Logger returns a sub-logger with block contexts added.
Logger(logger *zerolog.Logger) *zerolog.Logger
// GetShardState returns the deserialized shard state object.
GetShardState() (shard.State, error)
}

@ -183,9 +183,9 @@ func (consensus *Consensus) onAnnounce(msg *msg_pb.Message) {
}
// verify validity of block header object
blockHeader := recvMsg.Payload
headerObj := block.NewHeader()
err = rlp.DecodeBytes(blockHeader, headerObj)
encodedHeader := recvMsg.Payload
header := new(block.Header)
err = rlp.DecodeBytes(encodedHeader, header)
if err != nil {
consensus.getLogger().Warn().
Err(err).
@ -194,36 +194,36 @@ func (consensus *Consensus) onAnnounce(msg *msg_pb.Message) {
return
}
if recvMsg.BlockNum < consensus.blockNum || recvMsg.BlockNum != headerObj.Number().Uint64() {
if recvMsg.BlockNum < consensus.blockNum || recvMsg.BlockNum != header.Number().Uint64() {
consensus.getLogger().Debug().
Uint64("MsgBlockNum", recvMsg.BlockNum).
Uint64("blockNum", consensus.blockNum).
Uint64("hdrBlockNum", headerObj.Number().Uint64()).
Uint64("hdrBlockNum", header.Number().Uint64()).
Msg("[OnAnnounce] BlockNum does not match")
return
}
if consensus.mode.Mode() == Normal {
if err = chain.Engine.VerifyHeader(consensus.ChainReader, headerObj, true); err != nil {
if err = chain.Engine.VerifyHeader(consensus.ChainReader, header, true); err != nil {
consensus.getLogger().Warn().
Err(err).
Str("inChain", consensus.ChainReader.CurrentHeader().Number().String()).
Str("MsgBlockNum", headerObj.Number().String()).
Str("MsgBlockNum", header.Number().String()).
Msg("[OnAnnounce] Block content is not verified successfully")
return
}
//VRF/VDF is only generated in the beach chain
if consensus.NeedsRandomNumberGeneration(headerObj.Epoch()) {
if consensus.NeedsRandomNumberGeneration(header.Epoch()) {
//validate the VRF with proof if a non zero VRF is found in header
if len(headerObj.Vrf()) > 0 {
if !consensus.ValidateVrfAndProof(headerObj) {
if len(header.Vrf()) > 0 {
if !consensus.ValidateVrfAndProof(header) {
return
}
}
//validate the VDF with proof if a non zero VDF is found in header
if len(headerObj.Vdf()) > 0 {
if !consensus.ValidateVdfAndProof(headerObj) {
if len(header.Vdf()) > 0 {
if !consensus.ValidateVdfAndProof(header) {
return
}
}

@ -22,6 +22,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/block"
@ -38,6 +40,7 @@ type BlockGen struct {
i int
parent *types.Block
chain []*types.Block
factory blockfactory.Factory
header *block.Header
statedb *state.DB
@ -167,11 +170,12 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if config == nil {
config = params.TestChainConfig
}
factory := blockfactory.NewFactory(config)
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
chainreader := &fakeChainReader{config: config}
genblock := func(i int, parent *types.Block, statedb *state.DB) (*types.Block, types.Receipts) {
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
b.header = makeHeader(chainreader, parent, statedb, b.engine)
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, factory: factory, engine: engine}
b.header = makeHeader(chainreader, parent, statedb, b.engine, factory)
//if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 {
// misc.ApplyDAOHardFork(statedb)
@ -212,7 +216,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
return blocks, receipts
}
func makeHeader(chain consensus_engine.ChainReader, parent *types.Block, state *state.DB, engine consensus_engine.Engine) *block.Header {
func makeHeader(chain consensus_engine.ChainReader, parent *types.Block, state *state.DB, engine consensus_engine.Engine, factory blockfactory.Factory) *block.Header {
var time *big.Int
if parent.Time() == nil {
time = big.NewInt(10)
@ -220,13 +224,12 @@ func makeHeader(chain consensus_engine.ChainReader, parent *types.Block, state *
time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
}
return block.NewHeaderWith().
return factory.NewHeader(parent.Epoch()).With().
Root(state.IntermediateRoot(chain.Config().IsS3(parent.Epoch()))).
ParentHash(parent.Hash()).
Coinbase(parent.Coinbase()).
GasLimit(CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit())).
Number(new(big.Int).Add(parent.Number(), common.Big1)).
Epoch(parent.Epoch()).
Time(time).
Header()
}

@ -4,19 +4,19 @@ import (
"math/big"
"testing"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/core/types"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
)
func TestIsEpochBlock(t *testing.T) {
block1 := types.NewBlock(block.NewHeaderWith().Number(big.NewInt(10)).Header(), nil, nil, nil, nil)
block2 := types.NewBlock(block.NewHeaderWith().Number(big.NewInt(0)).Header(), nil, nil, nil, nil)
block3 := types.NewBlock(block.NewHeaderWith().Number(big.NewInt(344064)).Header(), nil, nil, nil, nil)
block4 := types.NewBlock(block.NewHeaderWith().Number(big.NewInt(77)).Header(), nil, nil, nil, nil)
block5 := types.NewBlock(block.NewHeaderWith().Number(big.NewInt(78)).Header(), nil, nil, nil, nil)
block6 := types.NewBlock(block.NewHeaderWith().Number(big.NewInt(188)).Header(), nil, nil, nil, nil)
block7 := types.NewBlock(block.NewHeaderWith().Number(big.NewInt(189)).Header(), nil, nil, nil, nil)
block1 := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(10)).Header(), nil, nil, nil, nil)
block2 := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(0)).Header(), nil, nil, nil, nil)
block3 := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(344064)).Header(), nil, nil, nil, nil)
block4 := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(77)).Header(), nil, nil, nil, nil)
block5 := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(78)).Header(), nil, nil, nil, nil)
block6 := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(188)).Header(), nil, nil, nil, nil)
block7 := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(189)).Header(), nil, nil, nil, nil)
tests := []struct {
schedule shardingconfig.Schedule
block *types.Block

@ -30,9 +30,10 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/core/rawdb"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -48,17 +49,18 @@ var errGenesisNoConfig = errors.New("genesis has no chain configuration")
// Genesis specifies the header fields, state of a genesis block. It also defines hard
// fork switch-over blocks through the chain configuration.
type Genesis struct {
Config *params.ChainConfig `json:"config"`
Nonce uint64 `json:"nonce"`
ShardID uint32 `json:"shardID"`
Timestamp uint64 `json:"timestamp"`
ExtraData []byte `json:"extraData"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc GenesisAlloc `json:"alloc" gencodec:"required"`
ShardStateHash common.Hash `json:"shardStateHash" gencodec:"required"`
ShardState shard.State `json:"shardState" gencodec:"required"`
Config *params.ChainConfig `json:"config"`
Factory blockfactory.Factory `json:"-"`
Nonce uint64 `json:"nonce"`
ShardID uint32 `json:"shardID"`
Timestamp uint64 `json:"timestamp"`
ExtraData []byte `json:"extraData"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc GenesisAlloc `json:"alloc" gencodec:"required"`
ShardStateHash common.Hash `json:"shardStateHash" gencodec:"required"`
ShardState shard.State `json:"shardState" gencodec:"required"`
// These fields are used for consensus tests. Please don't use them
// in actual genesis blocks.
@ -247,9 +249,8 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
utils.Logger().Error().Msg("failed to rlp-serialize genesis shard state")
os.Exit(1)
}
head := block.NewHeaderWith().
head := g.Factory.NewHeader(common.Big0).With().
Number(new(big.Int).SetUint64(g.Number)).
Epoch(big.NewInt(0)).
ShardID(g.ShardID).
Time(new(big.Int).SetUint64(g.Timestamp)).
ParentHash(g.ParentHash).
@ -316,6 +317,7 @@ func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big
func DefaultGenesisBlock() *Genesis {
return &Genesis{
Config: params.MainnetChainConfig,
Factory: blockfactory.ForMainnet,
Nonce: 66,
ExtraData: hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
GasLimit: 5000,

@ -31,6 +31,7 @@ import (
"golang.org/x/crypto/sha3"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
mock "github.com/harmony-one/harmony/core/rawdb/mock"
"github.com/harmony-one/harmony/core/types"
)
@ -40,7 +41,7 @@ func TestHeaderStorage(t *testing.T) {
db := ethdb.NewMemDatabase()
// Create a test header to move around the database and make sure it's really new
header := block.NewHeaderWith().Number(big.NewInt(42)).Extra([]byte("test header")).Header()
header := blockfactory.NewTestHeader().With().Number(big.NewInt(42)).Extra([]byte("test header")).Header()
if entry := ReadHeader(db, header.Hash(), header.Number().Uint64()); entry != nil {
t.Fatalf("Non existent header returned: %v", entry)
}
@ -73,7 +74,7 @@ func TestBodyStorage(t *testing.T) {
db := ethdb.NewMemDatabase()
// Create a test body to move around the database and make sure it's really new
body := &types.Body{Uncles: []*block.Header{block.NewHeaderWith().Extra([]byte("test header")).Header()}}
body := &types.Body{Uncles: []*block.Header{blockfactory.NewTestHeader().With().Extra([]byte("test header")).Header()}}
hasher := sha3.NewLegacyKeccak256()
rlp.Encode(hasher, body)
@ -111,11 +112,10 @@ func TestBlockStorage(t *testing.T) {
db := ethdb.NewMemDatabase()
// Create a test block to move around the database and make sure it's really new
block := types.NewBlockWithHeader(block.NewHeaderWith().
block := types.NewBlockWithHeader(blockfactory.NewTestHeader().With().
Extra([]byte("test block")).
TxHash(types.EmptyRootHash).
ReceiptHash(types.EmptyRootHash).
Epoch(big.NewInt(0)).
Number(big.NewInt(0)).
ShardState([]byte("dummy data")).
Header())
@ -171,7 +171,7 @@ func TestBlockStorage(t *testing.T) {
// Tests that partial block contents don't get reassembled into full blocks.
func TestPartialBlockStorage(t *testing.T) {
db := ethdb.NewMemDatabase()
block := types.NewBlockWithHeader(block.NewHeaderWith().
block := types.NewBlockWithHeader(blockfactory.NewTestHeader().With().
Extra([]byte("test block")).
TxHash(types.EmptyRootHash).
ReceiptHash(types.EmptyRootHash).
@ -251,9 +251,9 @@ func TestCanonicalMappingStorage(t *testing.T) {
func TestHeadStorage(t *testing.T) {
db := ethdb.NewMemDatabase()
blockHead := types.NewBlockWithHeader(block.NewHeaderWith().Extra([]byte("test block header")).Header())
blockFull := types.NewBlockWithHeader(block.NewHeaderWith().Extra([]byte("test block full")).Header())
blockFast := types.NewBlockWithHeader(block.NewHeaderWith().Extra([]byte("test block fast")).Header())
blockHead := types.NewBlockWithHeader(blockfactory.NewTestHeader().With().Extra([]byte("test block header")).Header())
blockFull := types.NewBlockWithHeader(blockfactory.NewTestHeader().With().Extra([]byte("test block full")).Header())
blockFast := types.NewBlockWithHeader(blockfactory.NewTestHeader().With().Extra([]byte("test block fast")).Header())
// Check that no head entries are in a pristine database
if entry := ReadHeadHeaderHash(db); entry != (common.Hash{}) {

@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
block2 "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/core/types"
)
@ -36,7 +36,7 @@ func TestLookupStorage(t *testing.T) {
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), 0, big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33})
txs := []*types.Transaction{tx1, tx2, tx3}
block := types.NewBlock(block2.NewHeaderWith().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
block := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
// Check that no transactions entries are in a pristine database
for i, tx := range txs {

@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -54,7 +54,7 @@ type testBlockChain struct {
}
func (bc *testBlockChain) CurrentBlock() *types.Block {
return types.NewBlock(block.NewHeaderWith().
return types.NewBlock(blockfactory.NewTestHeader().With().
GasLimit(bc.gasLimit).
Header(), nil, nil, nil, nil)
}

@ -21,7 +21,7 @@ import (
"bytes"
"testing"
"github.com/harmony-one/harmony/block"
blockfactory "github.com/harmony-one/harmony/block/factory"
)
var (
@ -96,7 +96,7 @@ func TestBlock_SetLastCommitSig(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b := &Block{header: block.NewHeader()}
b := &Block{header: blockfactory.NewTestHeader()}
b.SetLastCommitSig(tt.sig, tt.signers)
sig := b.header.LastCommitSignature()
if !bytes.Equal(tt.sig, sig[:]) {

@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls"
block2 "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/block/factory"
bls2 "github.com/harmony-one/harmony/crypto/bls"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
@ -128,7 +128,7 @@ func TestVrf(test *testing.T) {
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), 0, big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
txs := []*types.Transaction{tx1}
block := types.NewBlock(block2.NewHeaderWith().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
block := types.NewBlock(blockfactory.NewTestHeader().With().Number(big.NewInt(314)).Header(), txs, nil, nil, nil)
blockHash := block.Hash()
dRand.vrf(blockHash)

@ -22,6 +22,7 @@ require (
github.com/gorilla/mux v1.7.2
github.com/harmony-ek/gencodec v0.0.0-20190215044613-e6740dbdd846
github.com/harmony-one/bls v0.0.5
github.com/harmony-one/taggedrlp v0.1.2
github.com/harmony-one/vdf v1.0.0
github.com/hashicorp/golang-lru v0.5.1
github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365
@ -60,7 +61,7 @@ require (
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443
golang.org/x/lint v0.0.0-20190409202823-959b441ac422
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 // indirect
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd
golang.org/x/tools v0.0.0-20190827205025-b29f5f60c37a
google.golang.org/appengine v1.4.0 // indirect
google.golang.org/grpc v1.21.1
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127

@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/core"
common2 "github.com/harmony-one/harmony/internal/common"
@ -90,6 +91,7 @@ func (node *Node) SetupGenesisBlock(db ethdb.Database, shardID uint32, myShardSt
gspec := core.Genesis{
Config: &chainConfig,
Factory: blockfactory.NewFactory(&chainConfig),
Alloc: genesisAlloc,
ShardID: shardID,
GasLimit: params.GenesisGasLimit,

@ -5,11 +5,13 @@ import (
"math/big"
"time"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/shard"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/block"
@ -40,6 +42,7 @@ type environment struct {
// and gathering the sealing result.
type Worker struct {
config *params.ChainConfig
factory blockfactory.Factory
chain *core.BlockChain
current *environment // An environment for current running cycle.
@ -234,12 +237,11 @@ func (w *Worker) UpdateCurrent(coinbase common.Address) error {
// ... except if parent has a resharding assignment it increases by 1.
epoch = epoch.Add(epoch, common.Big1)
}
header := block.NewHeaderWith().
header := w.factory.NewHeader(epoch).With().
ParentHash(parent.Hash()).
Number(num.Add(num, common.Big1)).
GasLimit(core.CalcGasLimit(parent, w.gasFloor, w.gasCeil)).
Time(big.NewInt(timestamp)).
Epoch(epoch).
ShardID(w.chain.ShardID()).
Coinbase(coinbase).
Header()
@ -341,9 +343,10 @@ func (w *Worker) FinalizeNewBlock(sig []byte, signers []byte, viewID uint64, coi
// New create a new worker object.
func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus_engine.Engine, shardID uint32) *Worker {
worker := &Worker{
config: config,
chain: chain,
engine: engine,
config: config,
factory: blockfactory.NewFactory(config),
chain: chain,
engine: engine,
}
worker.gasFloor = 500000000000000000
worker.gasCeil = 1000000000000000000
@ -360,12 +363,11 @@ func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus_en
// ... except if parent has a resharding assignment it increases by 1.
epoch = epoch.Add(epoch, common.Big1)
}
header := block.NewHeaderWith().
header := worker.factory.NewHeader(epoch).With().
ParentHash(parent.Hash()).
Number(num.Add(num, common.Big1)).
GasLimit(core.CalcGasLimit(parent, worker.gasFloor, worker.gasCeil)).
Time(big.NewInt(timestamp)).
Epoch(epoch).
ShardID(worker.chain.ShardID()).
Header()
worker.makeCurrent(parent, header)

@ -5,6 +5,7 @@ import (
"math/rand"
"testing"
blockfactory "github.com/harmony-one/harmony/block/factory"
chain2 "github.com/harmony-one/harmony/internal/chain"
"github.com/ethereum/go-ethereum/crypto"
@ -22,7 +23,8 @@ var (
testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
testBankFunds = big.NewInt(8000000000000000000)
chainConfig = params.TestChainConfig
chainConfig = params.TestChainConfig
blockFactory = blockfactory.ForTest
)
func TestNewWorker(t *testing.T) {
@ -31,6 +33,7 @@ func TestNewWorker(t *testing.T) {
database = ethdb.NewMemDatabase()
gspec = core.Genesis{
Config: chainConfig,
Factory: blockFactory,
Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
ShardID: 10,
}
@ -54,6 +57,7 @@ func TestCommitTransactions(t *testing.T) {
database = ethdb.NewMemDatabase()
gspec = core.Genesis{
Config: chainConfig,
Factory: blockFactory,
Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
ShardID: 0,
}

@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/crypto/hash"
"github.com/ethereum/go-ethereum/ethdb"
@ -38,7 +39,8 @@ var (
testUserKey, _ = crypto.GenerateKey()
testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey)
chainConfig = params.TestChainConfig
chainConfig = params.TestChainConfig
blockFactory = blockfactory.ForTest
//StakingPriKey is the keys for the deposit contract.
StakingPriKey, _ = crypto.GenerateKey()
@ -52,6 +54,7 @@ var (
database = ethdb.NewMemDatabase()
gspec = core.Genesis{
Config: chainConfig,
Factory: blockFactory,
Alloc: core.GenesisAlloc{FaucetAddress: {Balance: FaucetInitFunds}},
ShardID: 0,
}

Loading…
Cancel
Save