Merge pull request #21 from filecoin-project/refac/types

Extract types needed for actors outside of chain
This commit is contained in:
Jakub Sztandera 2019-07-12 17:44:46 +02:00 committed by GitHub
commit c48a63b003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 326 additions and 256 deletions

View File

@ -6,6 +6,7 @@ import (
"sync" "sync"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
datastore "github.com/ipfs/go-datastore" datastore "github.com/ipfs/go-datastore"
@ -27,7 +28,7 @@ type GenesisBootstrap struct {
MinerKey address.Address MinerKey address.Address
} }
func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*Actor, error) { func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor, error) {
var ias InitActorState var ias InitActorState
ias.NextID = 100 ias.NextID = 100
@ -56,7 +57,7 @@ func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*Actor, erro
return nil, err return nil, err
} }
act := &Actor{ act := &types.Actor{
Code: InitActorCodeCid, Code: InitActorCodeCid,
Head: statecid, Head: statecid,
} }
@ -103,18 +104,18 @@ func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error
return nil, err return nil, err
} }
err = state.SetActor(NetworkAddress, &Actor{ err = state.SetActor(NetworkAddress, &types.Actor{
Code: AccountActorCodeCid, Code: AccountActorCodeCid,
Balance: NewInt(100000000000), Balance: types.NewInt(100000000000),
Head: emptyobject, Head: emptyobject,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = state.SetActor(minerAddr, &Actor{ err = state.SetActor(minerAddr, &types.Actor{
Code: AccountActorCodeCid, Code: AccountActorCodeCid,
Balance: NewInt(5000000), Balance: types.NewInt(5000000),
Head: emptyobject, Head: emptyobject,
}) })
if err != nil { if err != nil {
@ -140,7 +141,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error
ElectionProof: []byte("the Genesis block"), ElectionProof: []byte("the Genesis block"),
Parents: []cid.Cid{}, Parents: []cid.Cid{},
Height: 0, Height: 0,
ParentWeight: NewInt(0), ParentWeight: types.NewInt(0),
StateRoot: stateroot, StateRoot: stateroot,
Messages: emptyroot, Messages: emptyroot,
MessageReceipts: emptyroot, MessageReceipts: emptyroot,

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
) )
@ -12,7 +13,7 @@ type invoker struct {
builtInCode map[cid.Cid]nativeCode builtInCode map[cid.Cid]nativeCode
} }
type invokeFunc func(act *Actor, vmctx *VMContext, params []byte) (InvokeRet, error) type invokeFunc func(act *types.Actor, vmctx *VMContext, params []byte) (InvokeRet, error)
type nativeCode []invokeFunc type nativeCode []invokeFunc
type InvokeRet struct { type InvokeRet struct {
result []byte result []byte
@ -27,7 +28,7 @@ func newInvoker() *invoker {
return inv return inv
} }
func (inv *invoker) Invoke(act *Actor, vmctx *VMContext, method uint64, params []byte) (InvokeRet, error) { func (inv *invoker) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params []byte) (InvokeRet, error) {
code, ok := inv.builtInCode[act.Code] code, ok := inv.builtInCode[act.Code]
if !ok { if !ok {
@ -57,6 +58,7 @@ type Invokee interface {
} }
var tUnmarhsalCBOR = reflect.TypeOf((*unmarshalCBOR)(nil)).Elem() var tUnmarhsalCBOR = reflect.TypeOf((*unmarshalCBOR)(nil)).Elem()
var tVMContext = reflect.TypeOf((*types.VMContext)(nil)).Elem()
var tError = reflect.TypeOf((*error)(nil)).Elem() var tError = reflect.TypeOf((*error)(nil)).Elem()
func (*invoker) transform(instance Invokee) (nativeCode, error) { func (*invoker) transform(instance Invokee) (nativeCode, error) {
@ -77,13 +79,13 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) {
} }
if t.NumIn() != 3 { if t.NumIn() != 3 {
return nil, newErr("wrong number of inputs should be: " + return nil, newErr("wrong number of inputs should be: " +
"*Actor, *VMContext, <type of parameter>") "*types.Actor, *VMContext, <type of parameter>")
} }
if t.In(0) != reflect.TypeOf(&Actor{}) { if t.In(0) != reflect.TypeOf(&types.Actor{}) {
return nil, newErr("first arguemnt should be *Actor") return nil, newErr("first arguemnt should be *types.Actor")
} }
if t.In(1) != reflect.TypeOf(&VMContext{}) { if t.In(1) != tVMContext {
return nil, newErr("second argument should be *VMContext") return nil, newErr("second argument should be types.VMContext")
} }
if !t.In(2).Implements(tUnmarhsalCBOR) { if !t.In(2).Implements(tUnmarhsalCBOR) {

View File

@ -4,6 +4,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/filecoin-project/go-lotus/chain/types"
) )
type basicContract struct{} type basicContract struct{}
@ -32,13 +34,13 @@ func (b basicContract) Exports() []interface{} {
} }
} }
func (basicContract) InvokeSomething0(act *Actor, vmctx *VMContext, func (basicContract) InvokeSomething0(act *types.Actor, vmctx types.VMContext,
params *basicParams) (InvokeRet, error) { params *basicParams) (InvokeRet, error) {
return InvokeRet{ return InvokeRet{
returnCode: params.b, returnCode: params.b,
}, nil }, nil
} }
func (basicContract) InvokeSomething10(act *Actor, vmctx *VMContext, func (basicContract) InvokeSomething10(act *types.Actor, vmctx types.VMContext,
params *basicParams) (InvokeRet, error) { params *basicParams) (InvokeRet, error) {
return InvokeRet{ return InvokeRet{
returnCode: params.b + 10, returnCode: params.b + 10,
@ -53,7 +55,7 @@ func TestInvokerBasic(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, byte(1), ret.returnCode, "return code should be 1") assert.Equal(t, byte(1), ret.returnCode, "return code should be 1")
ret, err = code[10](nil, nil, []byte{2}) ret, err = code[10](nil, &VMContext{}, []byte{2})
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, byte(12), ret.returnCode, "return code should be 1") assert.Equal(t, byte(12), ret.returnCode, "return code should be 1")
} }

View File

@ -10,11 +10,12 @@ import (
sharray "github.com/whyrusleeping/sharray" sharray "github.com/whyrusleeping/sharray"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
bls "github.com/filecoin-project/go-lotus/lib/bls-signatures" bls "github.com/filecoin-project/go-lotus/lib/bls-signatures"
) )
func miningRewardForBlock(base *TipSet) BigInt { func miningRewardForBlock(base *TipSet) types.BigInt {
return NewInt(10000) return types.NewInt(10000)
} }
func MinerCreateBlock(cs *ChainStore, miner address.Address, parents *TipSet, tickets []Ticket, proof ElectionProof, msgs []*SignedMessage) (*FullBlock, error) { func MinerCreateBlock(cs *ChainStore, miner address.Address, parents *TipSet, tickets []Ticket, proof ElectionProof, msgs []*SignedMessage) (*FullBlock, error) {
@ -96,7 +97,7 @@ func MinerCreateBlock(cs *ChainStore, miner address.Address, parents *TipSet, ti
next.BLSAggregate = aggSig next.BLSAggregate = aggSig
next.StateRoot = stateRoot next.StateRoot = stateRoot
pweight := cs.Weight(parents) pweight := cs.Weight(parents)
next.ParentWeight = NewInt(pweight) next.ParentWeight = types.NewInt(pweight)
fullBlock := &FullBlock{ fullBlock := &FullBlock{
Header: next, Header: next,

View File

@ -4,11 +4,12 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
) )
var ErrActorNotFound = fmt.Errorf("actor not found") var ErrActorNotFound = fmt.Errorf("actor not found")
@ -17,7 +18,7 @@ type StateTree struct {
root *hamt.Node root *hamt.Node
store *hamt.CborIpldStore store *hamt.CborIpldStore
actorcache map[address.Address]*Actor actorcache map[address.Address]*types.Actor
snapshot cid.Cid snapshot cid.Cid
} }
@ -25,7 +26,7 @@ func NewStateTree(cst *hamt.CborIpldStore) (*StateTree, error) {
return &StateTree{ return &StateTree{
root: hamt.NewNode(cst), root: hamt.NewNode(cst),
store: cst, store: cst,
actorcache: make(map[address.Address]*Actor), actorcache: make(map[address.Address]*types.Actor),
}, nil }, nil
} }
@ -39,11 +40,11 @@ func LoadStateTree(cst *hamt.CborIpldStore, c cid.Cid) (*StateTree, error) {
return &StateTree{ return &StateTree{
root: nd, root: nd,
store: cst, store: cst,
actorcache: make(map[address.Address]*Actor), actorcache: make(map[address.Address]*types.Actor),
}, nil }, nil
} }
func (st *StateTree) SetActor(addr address.Address, act *Actor) error { func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error {
if addr.Protocol() != address.ID { if addr.Protocol() != address.ID {
iaddr, err := st.lookupID(addr) iaddr, err := st.lookupID(addr)
if err != nil { if err != nil {
@ -76,7 +77,7 @@ func (st *StateTree) lookupID(addr address.Address) (address.Address, error) {
return ias.Lookup(st.store, addr) return ias.Lookup(st.store, addr)
} }
func (st *StateTree) GetActor(addr address.Address) (*Actor, error) { func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
if addr.Protocol() != address.ID { if addr.Protocol() != address.ID {
iaddr, err := st.lookupID(addr) iaddr, err := st.lookupID(addr)
if err != nil { if err != nil {
@ -101,7 +102,7 @@ func (st *StateTree) GetActor(addr address.Address) (*Actor, error) {
return nil, err return nil, err
} }
var act Actor var act types.Actor
badout, err := cbor.DumpObject(thing) badout, err := cbor.DumpObject(thing)
if err != nil { if err != nil {
return nil, err return nil, err
@ -122,7 +123,7 @@ func (st *StateTree) Flush() (cid.Cid, error) {
return cid.Undef, err return cid.Undef, err
} }
} }
st.actorcache = make(map[address.Address]*Actor) st.actorcache = make(map[address.Address]*types.Actor)
if err := st.root.Flush(context.TODO()); err != nil { if err := st.root.Flush(context.TODO()); err != nil {
return cid.Undef, err return cid.Undef, err
@ -141,9 +142,9 @@ func (st *StateTree) Snapshot() error {
return nil return nil
} }
func (st *StateTree) RegisterNewAddress(addr address.Address, act *Actor) (address.Address, error) { func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor) (address.Address, error) {
var out address.Address var out address.Address
err := st.MutateActor(InitActorAddress, func(initact *Actor) error { err := st.MutateActor(InitActorAddress, func(initact *types.Actor) error {
var ias InitActorState var ias InitActorState
if err := st.store.Get(context.TODO(), initact.Head, &ias); err != nil { if err := st.store.Get(context.TODO(), initact.Head, &ias); err != nil {
return err return err
@ -185,7 +186,7 @@ func (st *StateTree) Revert() error {
return nil return nil
} }
func (st *StateTree) MutateActor(addr address.Address, f func(*Actor) error) error { func (st *StateTree) MutateActor(addr address.Address, f func(*types.Actor) error) error {
act, err := st.GetActor(addr) act, err := st.GetActor(addr)
if err != nil { if err != nil {
return err return err

View File

@ -6,6 +6,7 @@ import (
"sync" "sync"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore" dstore "github.com/ipfs/go-datastore"
@ -604,20 +605,20 @@ func (syncer *Syncer) ValidateBlock(b *FullBlock) error {
} }
func DeductFunds(act *Actor, amt BigInt) error { func DeductFunds(act *types.Actor, amt types.BigInt) error {
if BigCmp(act.Balance, amt) < 0 { if types.BigCmp(act.Balance, amt) < 0 {
return fmt.Errorf("not enough funds") return fmt.Errorf("not enough funds")
} }
act.Balance = BigSub(act.Balance, amt) act.Balance = types.BigSub(act.Balance, amt)
return nil return nil
} }
func DepositFunds(act *Actor, amt BigInt) { func DepositFunds(act *types.Actor, amt types.BigInt) {
act.Balance = BigAdd(act.Balance, amt) act.Balance = types.BigAdd(act.Balance, amt)
} }
func TryCreateAccountActor(st *StateTree, addr address.Address) (*Actor, error) { func TryCreateAccountActor(st *StateTree, addr address.Address) (*types.Actor, error) {
act, err := makeActor(st, addr) act, err := makeActor(st, addr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -631,7 +632,7 @@ func TryCreateAccountActor(st *StateTree, addr address.Address) (*Actor, error)
return act, nil return act, nil
} }
func makeActor(st *StateTree, addr address.Address) (*Actor, error) { func makeActor(st *StateTree, addr address.Address) (*types.Actor, error) {
switch addr.Protocol() { switch addr.Protocol() {
case address.BLS: case address.BLS:
return NewBLSAccountActor(st, addr) return NewBLSAccountActor(st, addr)
@ -646,7 +647,7 @@ func makeActor(st *StateTree, addr address.Address) (*Actor, error) {
} }
} }
func NewBLSAccountActor(st *StateTree, addr address.Address) (*Actor, error) { func NewBLSAccountActor(st *StateTree, addr address.Address) (*types.Actor, error) {
var acstate AccountActorState var acstate AccountActorState
acstate.Address = addr acstate.Address = addr
@ -655,19 +656,19 @@ func NewBLSAccountActor(st *StateTree, addr address.Address) (*Actor, error) {
return nil, err return nil, err
} }
nact := &Actor{ nact := &types.Actor{
Code: AccountActorCodeCid, Code: AccountActorCodeCid,
Balance: NewInt(0), Balance: types.NewInt(0),
Head: c, Head: c,
} }
return nact, nil return nact, nil
} }
func NewSecp256k1AccountActor(st *StateTree, addr address.Address) (*Actor, error) { func NewSecp256k1AccountActor(st *StateTree, addr address.Address) (*types.Actor, error) {
nact := &Actor{ nact := &types.Actor{
Code: AccountActorCodeCid, Code: AccountActorCodeCid,
Balance: NewInt(0), Balance: types.NewInt(0),
Head: EmptyObjectCid, Head: EmptyObjectCid,
} }

View File

@ -1,13 +1,9 @@
package chain package chain
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/big"
"github.com/filecoin-project/go-lotus/chain/address"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -15,30 +11,17 @@ import (
ipld "github.com/ipfs/go-ipld-format" ipld "github.com/ipfs/go-ipld-format"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
"github.com/polydawn/refmt/obj/atlas" "github.com/polydawn/refmt/obj/atlas"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
) )
func init() { func init() {
ipld.Register(0x1f, IpldDecode) ipld.Register(0x1f, IpldDecode)
cbor.RegisterCborType(MessageReceipt{})
cbor.RegisterCborType(Actor{})
cbor.RegisterCborType(BlockMsg{}) cbor.RegisterCborType(BlockMsg{})
///* ///*
cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).UseTag(2).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc(
func(i BigInt) ([]byte, error) {
if i.Int == nil {
return []byte{}, nil
}
return i.Bytes(), nil
})).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(x []byte) (BigInt, error) {
return BigFromBytes(x), nil
})).
Complete())
//*/ //*/
cbor.RegisterCborType(atlas.BuildEntry(SignedMessage{}).UseTag(45).Transform(). cbor.RegisterCborType(atlas.BuildEntry(SignedMessage{}).UseTag(45).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc( TransformMarshal(atlas.MakeMarshalTransformFunc(
@ -61,7 +44,7 @@ func init() {
} }
return SignedMessage{ return SignedMessage{
Message: x[0].(Message), Message: x[0].(types.Message),
Signature: sig, Signature: sig,
}, nil }, nil
})). })).
@ -78,63 +61,6 @@ func init() {
return SignatureFromBytes(x) return SignatureFromBytes(x)
})). })).
Complete()) Complete())
cbor.RegisterCborType(atlas.BuildEntry(Message{}).UseTag(44).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc(
func(m Message) ([]interface{}, error) {
return []interface{}{
m.To.Bytes(),
m.From.Bytes(),
m.Nonce,
m.Value,
m.GasPrice,
m.GasLimit,
m.Method,
m.Params,
}, nil
})).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(arr []interface{}) (Message, error) {
to, err := address.NewFromBytes(arr[0].([]byte))
if err != nil {
return Message{}, err
}
from, err := address.NewFromBytes(arr[1].([]byte))
if err != nil {
return Message{}, err
}
nonce, ok := arr[2].(uint64)
if !ok {
return Message{}, fmt.Errorf("expected uint64 nonce at index 2")
}
value := arr[3].(BigInt)
gasPrice := arr[4].(BigInt)
gasLimit := arr[5].(BigInt)
method, _ := arr[6].(uint64)
params, _ := arr[7].([]byte)
if gasPrice.Nil() {
gasPrice = NewInt(0)
}
if gasLimit.Nil() {
gasLimit = NewInt(0)
}
return Message{
To: to,
From: from,
Nonce: nonce,
Value: value,
GasPrice: gasPrice,
GasLimit: gasLimit,
Method: method,
Params: params,
}, nil
})).
Complete())
cbor.RegisterCborType(atlas.BuildEntry(BlockHeader{}).UseTag(43).Transform(). cbor.RegisterCborType(atlas.BuildEntry(BlockHeader{}).UseTag(43).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc( TransformMarshal(atlas.MakeMarshalTransformFunc(
func(blk BlockHeader) ([]interface{}, error) { func(blk BlockHeader) ([]interface{}, error) {
@ -175,7 +101,7 @@ func init() {
for _, p := range parentsArr { for _, p := range parentsArr {
parents = append(parents, p.(cid.Cid)) parents = append(parents, p.(cid.Cid))
} }
parentWeight := arr[4].(BigInt) parentWeight := arr[4].(types.BigInt)
height := arr[5].(uint64) height := arr[5].(uint64)
stateRoot := arr[6].(cid.Cid) stateRoot := arr[6].(cid.Cid)
@ -197,65 +123,6 @@ func init() {
Complete()) Complete())
} }
type BigInt struct {
*big.Int
}
func NewInt(i uint64) BigInt {
return BigInt{big.NewInt(0).SetUint64(i)}
}
func BigFromBytes(b []byte) BigInt {
i := big.NewInt(0).SetBytes(b)
return BigInt{i}
}
func BigMul(a, b BigInt) BigInt {
return BigInt{big.NewInt(0).Mul(a.Int, b.Int)}
}
func BigAdd(a, b BigInt) BigInt {
return BigInt{big.NewInt(0).Add(a.Int, b.Int)}
}
func BigSub(a, b BigInt) BigInt {
return BigInt{big.NewInt(0).Sub(a.Int, b.Int)}
}
func BigCmp(a, b BigInt) int {
return a.Int.Cmp(b.Int)
}
func (bi *BigInt) Nil() bool {
return bi.Int == nil
}
func (bi *BigInt) MarshalJSON() ([]byte, error) {
return json.Marshal(bi.String())
}
func (bi *BigInt) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
i, ok := big.NewInt(0).SetString(s, 10)
if !ok {
return fmt.Errorf("failed to parse bigint string")
}
bi.Int = i
return nil
}
type Actor struct {
Code cid.Cid
Head cid.Cid
Nonce uint64
Balance BigInt
}
type BlockHeader struct { type BlockHeader struct {
Miner address.Address Miner address.Address
@ -265,7 +132,7 @@ type BlockHeader struct {
Parents []cid.Cid Parents []cid.Cid
ParentWeight BigInt ParentWeight types.BigInt
Height uint64 Height uint64
@ -315,49 +182,6 @@ func (blk *BlockHeader) Serialize() ([]byte, error) {
return cbor.DumpObject(blk) return cbor.DumpObject(blk)
} }
type Message struct {
To address.Address
From address.Address
Nonce uint64
Value BigInt
GasPrice BigInt
GasLimit BigInt
Method uint64
Params []byte
}
func DecodeMessage(b []byte) (*Message, error) {
var msg Message
if err := cbor.DecodeInto(b, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (m *Message) Serialize() ([]byte, error) {
return cbor.DumpObject(m)
}
func (m *Message) ToStorageBlock() (block.Block, error) {
data, err := m.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 (m *SignedMessage) ToStorageBlock() (block.Block, error) { func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
data, err := m.Serialize() data, err := m.Serialize()
if err != nil { if err != nil {
@ -382,20 +206,8 @@ func (m *SignedMessage) Cid() cid.Cid {
return sb.Cid() return sb.Cid()
} }
type MessageReceipt struct {
ExitCode uint8
Return []byte
GasUsed BigInt
}
func (mr *MessageReceipt) Equals(o *MessageReceipt) bool {
return mr.ExitCode == o.ExitCode && bytes.Equal(mr.Return, o.Return) && BigCmp(mr.GasUsed, o.GasUsed) == 0
}
type SignedMessage struct { type SignedMessage struct {
Message Message Message types.Message
Signature Signature Signature Signature
} }
@ -546,7 +358,7 @@ func (f *filecoinIpldNode) Links() []*ipld.Link {
Cid: t.MessageReceipts, Cid: t.MessageReceipts,
}, },
} }
case Message: case types.Message:
return nil return nil
default: default:
panic("whats going on") panic("whats going on")

17
chain/types/actor.go Normal file
View File

@ -0,0 +1,17 @@
package types
import (
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
)
func init() {
cbor.RegisterCborType(Actor{})
}
type Actor struct {
Code cid.Cid
Head cid.Cid
Nonce uint64
Balance BigInt
}

79
chain/types/bigint.go Normal file
View File

@ -0,0 +1,79 @@
package types
import (
"encoding/json"
"fmt"
"math/big"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/polydawn/refmt/obj/atlas"
)
func init() {
cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).UseTag(2).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc(
func(i BigInt) ([]byte, error) {
if i.Int == nil {
return []byte{}, nil
}
return i.Bytes(), nil
})).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(x []byte) (BigInt, error) {
return BigFromBytes(x), nil
})).
Complete())
}
type BigInt struct {
*big.Int
}
func NewInt(i uint64) BigInt {
return BigInt{big.NewInt(0).SetUint64(i)}
}
func BigFromBytes(b []byte) BigInt {
i := big.NewInt(0).SetBytes(b)
return BigInt{i}
}
func BigMul(a, b BigInt) BigInt {
return BigInt{big.NewInt(0).Mul(a.Int, b.Int)}
}
func BigAdd(a, b BigInt) BigInt {
return BigInt{big.NewInt(0).Add(a.Int, b.Int)}
}
func BigSub(a, b BigInt) BigInt {
return BigInt{big.NewInt(0).Sub(a.Int, b.Int)}
}
func BigCmp(a, b BigInt) int {
return a.Int.Cmp(b.Int)
}
func (bi *BigInt) Nil() bool {
return bi.Int == nil
}
func (bi *BigInt) MarshalJSON() ([]byte, error) {
return json.Marshal(bi.String())
}
func (bi *BigInt) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
i, ok := big.NewInt(0).SetString(s, 10)
if !ok {
return fmt.Errorf("failed to parse bigint string")
}
bi.Int = i
return nil
}

116
chain/types/message.go Normal file
View File

@ -0,0 +1,116 @@
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(Message{}).UseTag(44).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc(
func(m Message) ([]interface{}, error) {
return []interface{}{
m.To.Bytes(),
m.From.Bytes(),
m.Nonce,
m.Value,
m.GasPrice,
m.GasLimit,
m.Method,
m.Params,
}, nil
})).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(arr []interface{}) (Message, error) {
to, err := address.NewFromBytes(arr[0].([]byte))
if err != nil {
return Message{}, err
}
from, err := address.NewFromBytes(arr[1].([]byte))
if err != nil {
return Message{}, err
}
nonce, ok := arr[2].(uint64)
if !ok {
return Message{}, fmt.Errorf("expected uint64 nonce at index 2")
}
value := arr[3].(BigInt)
gasPrice := arr[4].(BigInt)
gasLimit := arr[5].(BigInt)
method, _ := arr[6].(uint64)
params, _ := arr[7].([]byte)
if gasPrice.Nil() {
gasPrice = NewInt(0)
}
if gasLimit.Nil() {
gasLimit = NewInt(0)
}
return Message{
To: to,
From: from,
Nonce: nonce,
Value: value,
GasPrice: gasPrice,
GasLimit: gasLimit,
Method: method,
Params: params,
}, nil
})).
Complete())
}
type Message struct {
To address.Address
From address.Address
Nonce uint64
Value BigInt
GasPrice BigInt
GasLimit BigInt
Method uint64
Params []byte
}
func DecodeMessage(b []byte) (*Message, error) {
var msg Message
if err := cbor.DecodeInto(b, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (m *Message) Serialize() ([]byte, error) {
return cbor.DumpObject(m)
}
func (m *Message) ToStorageBlock() (block.Block, error) {
data, err := m.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)
}

View File

@ -0,0 +1,21 @@
package types
import (
"bytes"
cbor "github.com/ipfs/go-ipld-cbor"
)
func init() {
cbor.RegisterCborType(MessageReceipt{})
}
type MessageReceipt struct {
ExitCode uint8
Return []byte
GasUsed BigInt
}
func (mr *MessageReceipt) Equals(o *MessageReceipt) bool {
return mr.ExitCode == o.ExitCode && bytes.Equal(mr.Return, o.Return) && BigCmp(mr.GasUsed, o.GasUsed) == 0
}

16
chain/types/vmcontext.go Normal file
View File

@ -0,0 +1,16 @@
package types
import (
"math/big"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/ipfs/go-hamt-ipld"
)
type VMContext interface {
Message() *Message
Ipld() *hamt.CborIpldStore
Send(to address.Address, method string, value *big.Int, params []interface{}) ([][]byte, uint8, error)
BlockHeight() uint64
GasUsed() BigInt
}

View File

@ -6,6 +6,7 @@ import (
"math/big" "math/big"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/lib/bufbstore" "github.com/filecoin-project/go-lotus/lib/bufbstore"
bserv "github.com/ipfs/go-blockservice" bserv "github.com/ipfs/go-blockservice"
@ -18,13 +19,13 @@ import (
type VMContext struct { type VMContext struct {
state *StateTree state *StateTree
msg *Message msg *types.Message
height uint64 height uint64
cst *hamt.CborIpldStore cst *hamt.CborIpldStore
} }
// Message is the message that kicked off the current invocation // Message is the message that kicked off the current invocation
func (vmc *VMContext) Message() *Message { func (vmc *VMContext) Message() *types.Message {
return vmc.msg return vmc.msg
} }
@ -49,11 +50,11 @@ func (vmc *VMContext) BlockHeight() uint64 {
return vmc.height return vmc.height
} }
func (vmc *VMContext) GasUsed() BigInt { func (vmc *VMContext) GasUsed() types.BigInt {
return NewInt(0) return types.NewInt(0)
} }
func makeVMContext(state *StateTree, msg *Message, height uint64) *VMContext { func makeVMContext(state *StateTree, msg *types.Message, height uint64) *VMContext {
return &VMContext{ return &VMContext{
state: state, state: state,
msg: msg, msg: msg,
@ -90,7 +91,7 @@ func NewVM(base cid.Cid, height uint64, maddr address.Address, cs *ChainStore) (
}, nil }, nil
} }
func (vm *VM) ApplyMessage(msg *Message) (*MessageReceipt, error) { func (vm *VM) ApplyMessage(msg *types.Message) (*types.MessageReceipt, error) {
st := vm.cstate st := vm.cstate
st.Snapshot() st.Snapshot()
fromActor, err := st.GetActor(msg.From) fromActor, err := st.GetActor(msg.From)
@ -98,9 +99,9 @@ func (vm *VM) ApplyMessage(msg *Message) (*MessageReceipt, error) {
return nil, errors.Wrap(err, "from actor not found") return nil, errors.Wrap(err, "from actor not found")
} }
gascost := BigMul(msg.GasLimit, msg.GasPrice) gascost := types.BigMul(msg.GasLimit, msg.GasPrice)
totalCost := BigAdd(gascost, msg.Value) totalCost := types.BigAdd(gascost, msg.Value)
if BigCmp(fromActor.Balance, totalCost) < 0 { if types.BigCmp(fromActor.Balance, totalCost) < 0 {
return nil, fmt.Errorf("not enough funds") return nil, fmt.Errorf("not enough funds")
} }
@ -140,13 +141,13 @@ func (vm *VM) ApplyMessage(msg *Message) (*MessageReceipt, error) {
if errcode != 0 { if errcode != 0 {
// revert all state changes since snapshot // revert all state changes since snapshot
st.Revert() st.Revert()
gascost := BigMul(vmctx.GasUsed(), msg.GasPrice) gascost := types.BigMul(vmctx.GasUsed(), msg.GasPrice)
if err := DeductFunds(fromActor, gascost); err != nil { if err := DeductFunds(fromActor, gascost); err != nil {
panic("invariant violated: " + err.Error()) panic("invariant violated: " + err.Error())
} }
} else { } else {
// refund unused gas // refund unused gas
refund := BigMul(BigSub(msg.GasLimit, vmctx.GasUsed()), msg.GasPrice) refund := types.BigMul(types.BigSub(msg.GasLimit, vmctx.GasUsed()), msg.GasPrice)
DepositFunds(fromActor, refund) DepositFunds(fromActor, refund)
} }
} }
@ -157,10 +158,10 @@ func (vm *VM) ApplyMessage(msg *Message) (*MessageReceipt, error) {
return nil, errors.Wrap(err, "getting block miner actor failed") return nil, errors.Wrap(err, "getting block miner actor failed")
} }
gasReward := BigMul(msg.GasPrice, vmctx.GasUsed()) gasReward := types.BigMul(msg.GasPrice, vmctx.GasUsed())
DepositFunds(miner, gasReward) DepositFunds(miner, gasReward)
return &MessageReceipt{ return &types.MessageReceipt{
ExitCode: errcode, ExitCode: errcode,
Return: ret, Return: ret,
GasUsed: vmctx.GasUsed(), GasUsed: vmctx.GasUsed(),
@ -183,7 +184,7 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
return root, nil return root, nil
} }
func (vm *VM) TransferFunds(from, to address.Address, amt BigInt) error { func (vm *VM) TransferFunds(from, to address.Address, amt types.BigInt) error {
if from == to { if from == to {
return nil return nil
} }
@ -206,7 +207,7 @@ func (vm *VM) TransferFunds(from, to address.Address, amt BigInt) error {
return nil return nil
} }
func (vm *VM) Invoke(act *Actor, vmctx *VMContext, method uint64, params []byte) ([]byte, byte, error) { func (vm *VM) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params []byte) ([]byte, byte, error) {
ret, err := vm.inv.Invoke(act, vmctx, method, params) ret, err := vm.inv.Invoke(act, vmctx, method, params)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err