The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
woop/block/header.go

173 lines
5.0 KiB

package block
import (
"encoding/json"
"io"
"math/big"
"reflect"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
blockif "github.com/woop-chain/woop/block/interface"
v0 "github.com/woop-chain/woop/block/v0"
v1 "github.com/woop-chain/woop/block/v1"
v2 "github.com/woop-chain/woop/block/v2"
v3 "github.com/woop-chain/woop/block/v3"
"github.com/woop-chain/woop/crypto/hash"
"github.com/woop-chain/taggedrlp"
"github.com/pkg/errors"
"github.com/rs/zerolog"
)
// Header represents a block header in the Woop blockchain.
type Header struct {
blockif.Header
}
// HeaderPair ..
type HeaderPair struct {
BeaconHeader *Header `json:"beacon-chain-header"`
ShardHeader *Header `json:"shard-chain-header"`
}
var (
// ErrHeaderIsNil ..
ErrHeaderIsNil = errors.New("cannot encode nil header receiver")
)
// MarshalJSON ..
func (h Header) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
ParentHash common.Hash `json:"parentHash"`
UncleHash common.Hash `json:"sha3Uncles"`
Nonce types.BlockNonce `json:"nonce"`
Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot"`
TxHash common.Hash `json:"transactionsRoot"`
ReceiptHash common.Hash `json:"receiptsRoot"`
Bloom types.Bloom `json:"logsBloom"`
Difficulty *hexutil.Big `json:"difficulty"`
Number *hexutil.Big `json:"number"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
Time *hexutil.Big `json:"timestamp"`
Extra hexutil.Bytes `json:"extraData"`
MixDigest common.Hash `json:"mixHash"`
Hash common.Hash `json:"hash"`
// Additional Fields
ViewID *big.Int `json:"viewID"`
Epoch *big.Int `json:"epoch"`
ShardID uint32 `json:"shardID"`
}{
h.ParentHash(),
common.Hash{},
types.BlockNonce{},
h.Coinbase(),
h.Root(),
h.TxHash(),
h.ReceiptHash(),
h.Bloom(),
(*hexutil.Big)(big.NewInt(0)),
(*hexutil.Big)(h.Number()),
hexutil.Uint64(h.GasLimit()),
hexutil.Uint64(h.GasUsed()),
(*hexutil.Big)(h.Time()),
h.Extra(),
h.MixDigest(),
h.Hash(),
h.Header.ViewID(),
h.Header.Epoch(),
h.Header.ShardID(),
})
}
// String ..
func (h Header) String() string {
s, _ := json.Marshal(h)
return string(s)
}
// EncodeRLP encodes the header using tagged RLP representation.
func (h *Header) EncodeRLP(w io.Writer) error {
if h == nil {
return ErrHeaderIsNil
}
return HeaderRegistry.Encode(w, h.Header)
}
// DecodeRLP decodes the header using tagged RLP representation.
func (h *Header) DecodeRLP(s *rlp.Stream) error {
if h == nil {
return ErrHeaderIsNil
}
decoded, err := HeaderRegistry.Decode(s)
if err != nil {
return err
}
hif, ok := decoded.(blockif.Header)
if !ok {
return errors.Errorf(
"decoded object (type %s) does not implement Header interface",
taggedrlp.TypeName(reflect.TypeOf(decoded)))
}
h.Header = hif
return nil
}
// 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() common.Hash {
return hash.FromRLP(h)
}
// NumberU64 returns the block number of the header as a uint64.
func (h *Header) NumberU64() uint64 {
return h.Number().Uint64()
}
// 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
}
// With returns a field setter context for the header.
//
// Call a chain of setters on the returned field setter, followed by a call of
// Header method. Example:
//
// 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}
}
// IsLastBlockInEpoch returns True if it is the last block of the epoch.
// Note that the last block contains the shard state of the next epoch.
func (h *Header) IsLastBlockInEpoch() bool {
return len(h.ShardState()) > 0
}
// HeaderRegistry is the taggedrlp type registry for versioned headers.
var HeaderRegistry = taggedrlp.NewRegistry()
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() })
HeaderRegistry.MustRegister("v2", v2.NewHeader())
HeaderRegistry.MustAddFactory(func() interface{} { return v2.NewHeader() })
HeaderRegistry.MustRegister("v3", v3.NewHeader())
HeaderRegistry.MustAddFactory(func() interface{} { return v3.NewHeader() })
}