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

137 lines
3.8 KiB

package block
import (
"encoding/json"
"io"
"math/big"
"reflect"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
blockif "github.com/harmony-one/harmony/block/interface"
v0 "github.com/harmony-one/harmony/block/v0"
v1 "github.com/harmony-one/harmony/block/v1"
v2 "github.com/harmony-one/harmony/block/v2"
v3 "github.com/harmony-one/harmony/block/v3"
"github.com/harmony-one/harmony/crypto/hash"
"github.com/harmony-one/taggedrlp"
"github.com/pkg/errors"
"github.com/rs/zerolog"
)
// Header represents a block header in the Harmony 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 {
S uint32 `json:"shard-id"`
H string `json:"block-header-hash"`
N *big.Int `json:"block-number"`
V *big.Int `json:"view-id"`
E *big.Int `json:"epoch"`
}{
h.Header.ShardID(),
h.Header.Hash().Hex(),
h.Header.Number(),
h.Header.ViewID(),
h.Header.Epoch(),
})
}
// 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() ethcommon.Hash {
return hash.FromRLP(h)
}
// 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() })
}