2019-07-05 14:46:21 +00:00
|
|
|
package chain
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
2019-07-19 11:56:18 +00:00
|
|
|
bls "github.com/filecoin-project/go-bls-sigs"
|
2019-07-05 14:46:21 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
|
|
|
hamt "github.com/ipfs/go-hamt-ipld"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
sharray "github.com/whyrusleeping/sharray"
|
2019-07-08 15:14:36 +00:00
|
|
|
|
2019-07-12 23:52:25 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
2019-07-08 15:14:36 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/address"
|
2019-07-26 04:54:22 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/store"
|
2019-07-12 10:23:05 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/types"
|
2019-07-26 04:54:22 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
2019-07-05 14:46:21 +00:00
|
|
|
)
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
func miningRewardForBlock(base *types.TipSet) types.BigInt {
|
2019-07-12 10:23:05 +00:00
|
|
|
return types.NewInt(10000)
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
func MinerCreateBlock(cs *store.ChainStore, miner address.Address, parents *types.TipSet, tickets []types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
2019-07-11 02:36:43 +00:00
|
|
|
st, err := cs.TipSetState(parents.Cids())
|
2019-07-05 14:46:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "failed to load tipset state")
|
|
|
|
}
|
|
|
|
|
2019-07-11 02:36:43 +00:00
|
|
|
height := parents.Height() + uint64(len(tickets))
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
vm, err := vm.NewVM(st, height, miner, cs)
|
2019-07-11 02:36:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-07-05 14:46:21 +00:00
|
|
|
|
|
|
|
// apply miner reward
|
2019-07-12 23:52:25 +00:00
|
|
|
if err := vm.TransferFunds(actors.NetworkAddress, miner, miningRewardForBlock(parents)); err != nil {
|
2019-07-05 14:46:21 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-07-25 22:15:03 +00:00
|
|
|
next := &types.BlockHeader{
|
2019-07-11 02:36:43 +00:00
|
|
|
Miner: miner,
|
|
|
|
Parents: parents.Cids(),
|
|
|
|
Tickets: tickets,
|
2019-07-05 14:46:21 +00:00
|
|
|
Height: height,
|
|
|
|
}
|
|
|
|
|
2019-07-11 02:36:43 +00:00
|
|
|
fmt.Printf("adding %d messages to block...", len(msgs))
|
2019-07-05 14:46:21 +00:00
|
|
|
var msgCids []cid.Cid
|
2019-07-24 05:38:16 +00:00
|
|
|
var blsSigs []types.Signature
|
2019-07-05 14:46:21 +00:00
|
|
|
var receipts []interface{}
|
2019-07-11 02:36:43 +00:00
|
|
|
for _, msg := range msgs {
|
2019-07-05 14:46:21 +00:00
|
|
|
if msg.Signature.TypeCode() == 2 {
|
|
|
|
blsSigs = append(blsSigs, msg.Signature)
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
c, err := cs.PutMessage(&msg.Message)
|
2019-07-05 14:46:21 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
msgCids = append(msgCids, c)
|
2019-07-05 14:46:21 +00:00
|
|
|
} else {
|
|
|
|
msgCids = append(msgCids, msg.Cid())
|
|
|
|
}
|
|
|
|
rec, err := vm.ApplyMessage(&msg.Message)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "apply message failure")
|
|
|
|
}
|
|
|
|
|
|
|
|
receipts = append(receipts, rec)
|
|
|
|
}
|
|
|
|
|
2019-07-26 04:54:22 +00:00
|
|
|
cst := hamt.CSTFromBstore(cs.Blockstore())
|
2019-07-05 14:46:21 +00:00
|
|
|
msgroot, err := sharray.Build(context.TODO(), 4, toIfArr(msgCids), cst)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
next.Messages = msgroot
|
|
|
|
|
|
|
|
rectroot, err := sharray.Build(context.TODO(), 4, receipts, cst)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
next.MessageReceipts = rectroot
|
|
|
|
|
|
|
|
stateRoot, err := vm.Flush(context.TODO())
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "flushing state tree failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
aggSig, err := aggregateSignatures(blsSigs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
next.BLSAggregate = aggSig
|
|
|
|
next.StateRoot = stateRoot
|
2019-07-11 02:36:43 +00:00
|
|
|
pweight := cs.Weight(parents)
|
2019-07-12 10:23:05 +00:00
|
|
|
next.ParentWeight = types.NewInt(pweight)
|
2019-07-05 14:46:21 +00:00
|
|
|
|
2019-07-25 22:15:03 +00:00
|
|
|
fullBlock := &types.FullBlock{
|
2019-07-05 14:46:21 +00:00
|
|
|
Header: next,
|
2019-07-11 02:36:43 +00:00
|
|
|
Messages: msgs,
|
2019-07-05 14:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return fullBlock, nil
|
|
|
|
}
|
|
|
|
|
2019-07-24 05:38:16 +00:00
|
|
|
func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
|
2019-07-05 14:46:21 +00:00
|
|
|
var blsSigs []bls.Signature
|
|
|
|
for _, s := range sigs {
|
|
|
|
var bsig bls.Signature
|
|
|
|
copy(bsig[:], s.Data)
|
|
|
|
blsSigs = append(blsSigs, bsig)
|
|
|
|
}
|
|
|
|
|
|
|
|
aggSig := bls.Aggregate(blsSigs)
|
2019-07-24 05:38:16 +00:00
|
|
|
return types.Signature{
|
|
|
|
Type: types.KTBLS,
|
2019-07-05 14:46:21 +00:00
|
|
|
Data: aggSig[:],
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func toIfArr(cids []cid.Cid) []interface{} {
|
|
|
|
out := make([]interface{}, 0, len(cids))
|
|
|
|
for _, c := range cids {
|
|
|
|
out = append(out, c)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|