lotus/chain/gen/mining.go

191 lines
4.9 KiB
Go
Raw Normal View History

2019-07-25 22:15:33 +00:00
package gen
2019-07-05 14:46:21 +00:00
import (
"context"
2019-09-06 20:03:28 +00:00
2019-09-17 01:56:37 +00:00
amt "github.com/filecoin-project/go-amt-ipld"
2019-09-06 20:03:28 +00:00
bls "github.com/filecoin-project/go-bls-sigs"
cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
2019-07-05 14:46:21 +00:00
"github.com/pkg/errors"
2019-09-17 01:56:37 +00:00
cbg "github.com/whyrusleeping/cbor-gen"
2019-08-27 00:46:39 +00:00
"golang.org/x/xerrors"
2019-07-12 23:52:25 +00:00
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"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-08-27 00:46:39 +00:00
"github.com/filecoin-project/go-lotus/chain/wallet"
2019-07-05 14:46:21 +00:00
)
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
st, err := sm.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
vmi, err := vm.NewVM(st, height, miner, sm.ChainStore())
2019-07-11 02:36:43 +00:00
if err != nil {
return nil, err
}
2019-07-05 14:46:21 +00:00
owner, err := stmgr.GetMinerOwner(ctx, sm, st, miner)
2019-08-27 00:46:39 +00:00
if err != nil {
return nil, xerrors.Errorf("failed to get miner owner: %w", err)
}
worker, err := stmgr.GetMinerWorker(ctx, sm, st, miner)
2019-08-27 00:46:39 +00:00
if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
}
2019-07-05 14:46:21 +00:00
// apply miner reward
2019-08-27 00:46:39 +00:00
if err := vmi.TransferFunds(actors.NetworkAddress, owner, vm.MiningRewardForBlock(parents)); err != nil {
2019-07-05 14:46:21 +00:00
return nil, err
}
next := &types.BlockHeader{
Miner: miner,
Parents: parents.Cids(),
Tickets: tickets,
Height: height,
Timestamp: timestamp,
ElectionProof: proof,
2019-07-05 14:46:21 +00:00
}
var blsMessages []*types.Message
var secpkMessages []*types.SignedMessage
var blsMsgCids, secpkMsgCids []cid.Cid
var blsSigs []types.Signature
2019-07-11 02:36:43 +00:00
for _, msg := range msgs {
if msg.Signature.TypeCode() == types.IKTBLS {
2019-07-05 14:46:21 +00:00
blsSigs = append(blsSigs, msg.Signature)
blsMessages = append(blsMessages, &msg.Message)
2019-07-05 14:46:21 +00:00
c, err := sm.ChainStore().PutMessage(&msg.Message)
2019-07-05 14:46:21 +00:00
if err != nil {
return nil, err
}
blsMsgCids = append(blsMsgCids, c)
2019-07-05 14:46:21 +00:00
} else {
secpkMsgCids = append(secpkMsgCids, msg.Cid())
secpkMessages = append(secpkMessages, msg)
2019-07-05 14:46:21 +00:00
}
}
2019-09-17 01:56:37 +00:00
var receipts []cbg.CBORMarshaler
for _, msg := range blsMessages {
rec, err := vmi.ApplyMessage(ctx, msg)
if err != nil {
return nil, errors.Wrap(err, "apply message failure")
}
2019-09-17 01:56:37 +00:00
receipts = append(receipts, &rec.MessageReceipt)
}
for _, msg := range secpkMessages {
2019-07-26 12:28:29 +00:00
rec, err := vmi.ApplyMessage(ctx, &msg.Message)
2019-07-05 14:46:21 +00:00
if err != nil {
return nil, errors.Wrap(err, "apply message failure")
}
2019-09-17 01:56:37 +00:00
receipts = append(receipts, &rec.MessageReceipt)
2019-07-05 14:46:21 +00:00
}
2019-09-17 01:56:37 +00:00
bs := amt.WrapBlockstore(sm.ChainStore().Blockstore())
blsmsgroot, err := amt.FromArray(bs, toIfArr(blsMsgCids))
if err != nil {
2019-09-17 01:56:37 +00:00
return nil, xerrors.Errorf("building bls amt: %w", err)
}
2019-09-17 01:56:37 +00:00
secpkmsgroot, err := amt.FromArray(bs, toIfArr(secpkMsgCids))
if err != nil {
2019-09-17 01:56:37 +00:00
return nil, xerrors.Errorf("building secpk amt: %w", err)
}
2019-09-17 01:56:37 +00:00
mmcid, err := bs.Put(&types.MsgMeta{
BlsMessages: blsmsgroot,
SecpkMessages: secpkmsgroot,
})
2019-07-05 14:46:21 +00:00
if err != nil {
return nil, err
}
next.Messages = mmcid
2019-07-05 14:46:21 +00:00
2019-09-17 01:56:37 +00:00
rectroot, err := amt.FromArray(bs, receipts)
2019-07-05 14:46:21 +00:00
if err != nil {
2019-09-17 01:56:37 +00:00
return nil, xerrors.Errorf("failed to build receipts amt: %w", err)
2019-07-05 14:46:21 +00:00
}
next.MessageReceipts = rectroot
2019-07-26 12:28:29 +00:00
stateRoot, err := vmi.Flush(context.TODO())
2019-07-05 14:46:21 +00:00
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
pweight := sm.ChainStore().Weight(parents)
next.ParentWeight = types.NewInt(pweight)
2019-07-05 14:46:21 +00:00
2019-08-27 00:46:39 +00:00
// TODO: set timestamp
2019-09-11 20:10:29 +00:00
nosigbytes, err := next.SigningBytes()
2019-08-27 00:46:39 +00:00
if err != nil {
2019-09-11 20:10:29 +00:00
return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err)
2019-08-27 00:46:39 +00:00
}
2019-09-17 01:56:37 +00:00
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
2019-08-27 00:46:39 +00:00
waddr, err := vm.ResolveToKeyAddr(vmi.StateTree(), cst, worker)
if err != nil {
return nil, xerrors.Errorf("failed to resolve miner address to key address: %w", err)
}
sig, err := w.Sign(ctx, waddr, nosigbytes)
if err != nil {
return nil, xerrors.Errorf("failed to sign new block: %w", err)
}
next.BlockSig = *sig
fullBlock := &types.FullBlock{
Header: next,
BlsMessages: blsMessages,
SecpkMessages: secpkMessages,
2019-07-05 14:46:21 +00:00
}
return fullBlock, nil
}
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)
return types.Signature{
Type: types.KTBLS,
2019-07-05 14:46:21 +00:00
Data: aggSig[:],
}, nil
}
2019-09-17 01:56:37 +00:00
func toIfArr(cids []cid.Cid) []cbg.CBORMarshaler {
out := make([]cbg.CBORMarshaler, 0, len(cids))
2019-07-05 14:46:21 +00:00
for _, c := range cids {
2019-09-17 01:56:37 +00:00
oc := cbg.CborCid(c)
out = append(out, &oc)
2019-07-05 14:46:21 +00:00
}
return out
}