lotus/chain/types/blockheader.go
2019-08-16 12:39:12 -07:00

172 lines
3.6 KiB
Go

package types
import (
"fmt"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/multiformats/go-multihash"
"github.com/polydawn/refmt/obj/atlas"
"github.com/filecoin-project/go-lotus/chain/address"
)
func init() {
cbor.RegisterCborType(atlas.BuildEntry(BlockHeader{}).UseTag(43).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc(
func(blk BlockHeader) ([]interface{}, error) {
if blk.Tickets == nil {
blk.Tickets = []*Ticket{}
}
if blk.Parents == nil {
blk.Parents = []cid.Cid{}
}
var tickarrs [][][]byte // oh boy
for _, t := range blk.Tickets {
tickarrs = append(tickarrs, [][]byte{
t.VRFProof, t.VDFResult, t.VDFProof,
})
}
return []interface{}{
blk.Miner.Bytes(),
tickarrs,
blk.ElectionProof,
blk.Parents,
blk.ParentWeight,
blk.Height,
blk.StateRoot,
blk.Messages,
blk.MessageReceipts,
}, nil
})).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(arr []interface{}) (BlockHeader, error) {
miner, err := address.NewFromBytes(arr[0].([]byte))
if err != nil {
return BlockHeader{}, err
}
tickets := []*Ticket{}
ticketarr, _ := arr[1].([]interface{})
for _, t := range ticketarr {
ticklist, ok := t.([]interface{})
if !ok {
return BlockHeader{}, fmt.Errorf("tickets were incorrectly formatted (type = %T)", t)
}
if len(ticklist) != 3 {
return BlockHeader{}, fmt.Errorf("ticket should be a three item array of Byte arrays (got len = %d)", len(ticklist))
}
tickets = append(tickets, &Ticket{
VRFProof: ticklist[0].([]byte),
VDFResult: ticklist[1].([]byte),
VDFProof: ticklist[2].([]byte),
})
}
electionProof, _ := arr[2].([]byte)
parents := []cid.Cid{}
parentsArr, _ := arr[3].([]interface{})
for _, p := range parentsArr {
parents = append(parents, p.(cid.Cid))
}
parentWeight := arr[4].(BigInt)
height := arr[5].(uint64)
stateRoot := arr[6].(cid.Cid)
msgscid := arr[7].(cid.Cid)
recscid := arr[8].(cid.Cid)
return BlockHeader{
Miner: miner,
Tickets: tickets,
ElectionProof: electionProof,
Parents: parents,
ParentWeight: parentWeight,
Height: height,
StateRoot: stateRoot,
Messages: msgscid,
MessageReceipts: recscid,
}, nil
})).
Complete())
cbor.RegisterCborType(MsgMeta{})
cbor.RegisterCborType(Ticket{})
}
type Ticket struct {
VRFProof []byte
VDFResult []byte
VDFProof []byte
}
type ElectionProof []byte
type BlockHeader struct {
Miner address.Address
Tickets []*Ticket
ElectionProof []byte
Parents []cid.Cid
ParentWeight BigInt
Height uint64
StateRoot cid.Cid
Messages cid.Cid
BLSAggregate Signature
MessageReceipts cid.Cid
}
type MsgMeta struct {
BlsMessages cid.Cid
SecpkMessages cid.Cid
}
func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
data, err := b.Serialize()
if err != nil {
return nil, err
}
pref := cid.NewPrefixV1(0x1f, multihash.BLAKE2B_MIN+31)
c, err := pref.Sum(data)
if err != nil {
return nil, err
}
return block.NewBlockWithCid(data, c)
}
func (b *BlockHeader) Cid() cid.Cid {
sb, err := b.ToStorageBlock()
if err != nil {
panic(err)
}
return sb.Cid()
}
func DecodeBlock(b []byte) (*BlockHeader, error) {
var blk BlockHeader
if err := cbor.DecodeInto(b, &blk); err != nil {
return nil, err
}
return &blk, nil
}
func (blk *BlockHeader) Serialize() ([]byte, error) {
return cbor.DumpObject(blk)
}