decommission chain validation.
This commit is contained in:
parent
0ad0d4ea11
commit
798061506e
@ -1,215 +0,0 @@
|
|||||||
package validation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/puppet"
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
|
|
||||||
vtypes "github.com/filecoin-project/chain-validation/chain/types"
|
|
||||||
vstate "github.com/filecoin-project/chain-validation/state"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Applier applies messages to state trees and storage.
|
|
||||||
type Applier struct {
|
|
||||||
stateWrapper *StateWrapper
|
|
||||||
syscalls vm.SyscallBuilder
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ vstate.Applier = &Applier{}
|
|
||||||
|
|
||||||
func NewApplier(sw *StateWrapper, syscalls vm.SyscallBuilder) *Applier {
|
|
||||||
return &Applier{sw, syscalls}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Applier) ApplyMessage(epoch abi.ChainEpoch, message *vtypes.Message) (vtypes.ApplyMessageResult, error) {
|
|
||||||
lm := toLotusMsg(message)
|
|
||||||
receipt, penalty, reward, err := a.applyMessage(epoch, lm)
|
|
||||||
return vtypes.ApplyMessageResult{
|
|
||||||
Msg: *message,
|
|
||||||
Receipt: receipt,
|
|
||||||
Penalty: penalty,
|
|
||||||
Reward: reward,
|
|
||||||
Root: a.stateWrapper.Root().String(),
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Applier) ApplySignedMessage(epoch abi.ChainEpoch, msg *vtypes.SignedMessage) (vtypes.ApplyMessageResult, error) {
|
|
||||||
var lm types.ChainMsg
|
|
||||||
switch msg.Signature.Type {
|
|
||||||
case crypto.SigTypeSecp256k1:
|
|
||||||
lm = toLotusSignedMsg(msg)
|
|
||||||
case crypto.SigTypeBLS:
|
|
||||||
lm = toLotusMsg(&msg.Message)
|
|
||||||
default:
|
|
||||||
return vtypes.ApplyMessageResult{}, xerrors.New("Unknown signature type")
|
|
||||||
}
|
|
||||||
// TODO: Validate the sig first
|
|
||||||
receipt, penalty, reward, err := a.applyMessage(epoch, lm)
|
|
||||||
return vtypes.ApplyMessageResult{
|
|
||||||
Msg: msg.Message,
|
|
||||||
Receipt: receipt,
|
|
||||||
Penalty: penalty,
|
|
||||||
Reward: reward,
|
|
||||||
Root: a.stateWrapper.Root().String(),
|
|
||||||
}, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.BlockMessagesInfo, rnd vstate.RandomnessSource) (vtypes.ApplyTipSetResult, error) {
|
|
||||||
cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls)
|
|
||||||
sm := stmgr.NewStateManager(cs)
|
|
||||||
|
|
||||||
var bms []store.BlockMessages
|
|
||||||
for _, b := range blocks {
|
|
||||||
bm := store.BlockMessages{
|
|
||||||
Miner: b.Miner,
|
|
||||||
WinCount: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range b.BLSMessages {
|
|
||||||
bm.BlsMessages = append(bm.BlsMessages, toLotusMsg(m))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range b.SECPMessages {
|
|
||||||
bm.SecpkMessages = append(bm.SecpkMessages, toLotusSignedMsg(m))
|
|
||||||
}
|
|
||||||
|
|
||||||
bms = append(bms, bm)
|
|
||||||
}
|
|
||||||
|
|
||||||
var receipts []vtypes.MessageReceipt
|
|
||||||
// TODO: base fee
|
|
||||||
sroot, _, err := sm.ApplyBlocks(context.TODO(), epoch-1, a.stateWrapper.Root(), bms, epoch, &randWrapper{rnd}, func(c cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
|
||||||
if msg.From == builtin.SystemActorAddr {
|
|
||||||
return nil // ignore reward and cron calls
|
|
||||||
}
|
|
||||||
rval := ret.Return
|
|
||||||
if rval == nil {
|
|
||||||
rval = []byte{} // chain validation tests expect empty arrays to not be nil...
|
|
||||||
}
|
|
||||||
receipts = append(receipts, vtypes.MessageReceipt{
|
|
||||||
ExitCode: ret.ExitCode,
|
|
||||||
ReturnValue: rval,
|
|
||||||
|
|
||||||
GasUsed: vtypes.GasUnits(ret.GasUsed),
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}, abi.NewTokenAmount(100))
|
|
||||||
if err != nil {
|
|
||||||
return vtypes.ApplyTipSetResult{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
a.stateWrapper.stateRoot = sroot
|
|
||||||
|
|
||||||
return vtypes.ApplyTipSetResult{
|
|
||||||
Receipts: receipts,
|
|
||||||
Root: a.stateWrapper.Root().String(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type randWrapper struct {
|
|
||||||
rand vstate.RandomnessSource
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: these should really be two different randomness sources
|
|
||||||
func (w *randWrapper) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
|
||||||
return w.rand.Randomness(ctx, pers, round, entropy)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *randWrapper) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
|
||||||
return w.rand.Randomness(ctx, pers, round, entropy)
|
|
||||||
}
|
|
||||||
|
|
||||||
type vmRand struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*vmRand) GetChainRandomness(ctx context.Context, dst crypto.DomainSeparationTag, h abi.ChainEpoch, input []byte) ([]byte, error) {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*vmRand) GetBeaconRandomness(ctx context.Context, dst crypto.DomainSeparationTag, h abi.ChainEpoch, input []byte) ([]byte, error) {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Applier) applyMessage(epoch abi.ChainEpoch, lm types.ChainMsg) (vtypes.MessageReceipt, abi.TokenAmount, abi.TokenAmount, error) {
|
|
||||||
ctx := context.TODO()
|
|
||||||
base := a.stateWrapper.Root()
|
|
||||||
|
|
||||||
vmopt := &vm.VMOpts{
|
|
||||||
StateBase: base,
|
|
||||||
Epoch: epoch,
|
|
||||||
Rand: &vmRand{},
|
|
||||||
Bstore: a.stateWrapper.bs,
|
|
||||||
Syscalls: a.syscalls,
|
|
||||||
CircSupplyCalc: nil,
|
|
||||||
BaseFee: abi.NewTokenAmount(100),
|
|
||||||
}
|
|
||||||
|
|
||||||
lotusVM, err := vm.NewVM(vmopt)
|
|
||||||
// need to modify the VM invoker to add the puppet actor
|
|
||||||
chainValInvoker := vm.NewInvoker()
|
|
||||||
chainValInvoker.Register(puppet.PuppetActorCodeID, puppet.Actor{}, puppet.State{})
|
|
||||||
lotusVM.SetInvoker(chainValInvoker)
|
|
||||||
if err != nil {
|
|
||||||
return vtypes.MessageReceipt{}, big.Zero(), big.Zero(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret, err := lotusVM.ApplyMessage(ctx, lm)
|
|
||||||
if err != nil {
|
|
||||||
return vtypes.MessageReceipt{}, big.Zero(), big.Zero(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
rval := ret.Return
|
|
||||||
if rval == nil {
|
|
||||||
rval = []byte{}
|
|
||||||
}
|
|
||||||
|
|
||||||
a.stateWrapper.stateRoot, err = lotusVM.Flush(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return vtypes.MessageReceipt{}, big.Zero(), big.Zero(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
mr := vtypes.MessageReceipt{
|
|
||||||
ExitCode: ret.ExitCode,
|
|
||||||
ReturnValue: rval,
|
|
||||||
GasUsed: vtypes.GasUnits(ret.GasUsed),
|
|
||||||
}
|
|
||||||
|
|
||||||
return mr, ret.Penalty, abi.NewTokenAmount(ret.GasUsed), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func toLotusMsg(msg *vtypes.Message) *types.Message {
|
|
||||||
return &types.Message{
|
|
||||||
To: msg.To,
|
|
||||||
From: msg.From,
|
|
||||||
|
|
||||||
Nonce: msg.CallSeqNum,
|
|
||||||
Method: msg.Method,
|
|
||||||
|
|
||||||
Value: msg.Value,
|
|
||||||
GasLimit: msg.GasLimit,
|
|
||||||
GasFeeCap: msg.GasFeeCap,
|
|
||||||
GasPremium: msg.GasPremium,
|
|
||||||
|
|
||||||
Params: msg.Params,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toLotusSignedMsg(msg *vtypes.SignedMessage) *types.SignedMessage {
|
|
||||||
return &types.SignedMessage{
|
|
||||||
Message: *toLotusMsg(&msg.Message),
|
|
||||||
Signature: msg.Signature,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package validation
|
|
||||||
|
|
||||||
//
|
|
||||||
// Config
|
|
||||||
//
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
trackGas bool
|
|
||||||
checkExitCode bool
|
|
||||||
checkReturnValue bool
|
|
||||||
checkState bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfig(gas, exit, ret, state bool) *Config {
|
|
||||||
return &Config{
|
|
||||||
trackGas: gas,
|
|
||||||
checkExitCode: exit,
|
|
||||||
checkReturnValue: ret,
|
|
||||||
checkState: state,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Config) ValidateGas() bool {
|
|
||||||
return v.trackGas
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Config) ValidateExitCode() bool {
|
|
||||||
return v.checkExitCode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Config) ValidateReturnValue() bool {
|
|
||||||
return v.checkReturnValue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Config) ValidateStateRoot() bool {
|
|
||||||
return v.checkState
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package validation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
|
||||||
|
|
||||||
vstate "github.com/filecoin-project/chain-validation/state"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Factories struct {
|
|
||||||
*Applier
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ vstate.Factories = &Factories{}
|
|
||||||
|
|
||||||
func NewFactories() *Factories {
|
|
||||||
return &Factories{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Factories) NewStateAndApplier(syscalls runtime.Syscalls) (vstate.VMWrapper, vstate.Applier) {
|
|
||||||
st := NewState()
|
|
||||||
return st, NewApplier(st, func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls {
|
|
||||||
return syscalls
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Factories) NewKeyManager() vstate.KeyManager {
|
|
||||||
return newKeyManager()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Factories) NewValidationConfig() vstate.ValidationConfig {
|
|
||||||
trackGas := true
|
|
||||||
checkExit := true
|
|
||||||
checkRet := true
|
|
||||||
checkState := true
|
|
||||||
return NewConfig(trackGas, checkExit, checkRet, checkState)
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package validation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/minio/blake2b-simd"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-crypto"
|
|
||||||
acrypto "github.com/filecoin-project/specs-actors/actors/crypto"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KeyManager struct {
|
|
||||||
// Private keys by address
|
|
||||||
keys map[address.Address]*wallet.Key
|
|
||||||
|
|
||||||
// Seed for deterministic secp key generation.
|
|
||||||
secpSeed int64
|
|
||||||
// Seed for deterministic bls key generation.
|
|
||||||
blsSeed int64 // nolint: structcheck
|
|
||||||
}
|
|
||||||
|
|
||||||
func newKeyManager() *KeyManager {
|
|
||||||
return &KeyManager{
|
|
||||||
keys: make(map[address.Address]*wallet.Key),
|
|
||||||
secpSeed: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyManager) NewSECP256k1AccountAddress() address.Address {
|
|
||||||
secpKey := k.newSecp256k1Key()
|
|
||||||
k.keys[secpKey.Address] = secpKey
|
|
||||||
return secpKey.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyManager) NewBLSAccountAddress() address.Address {
|
|
||||||
blsKey := k.newBLSKey()
|
|
||||||
k.keys[blsKey.Address] = blsKey
|
|
||||||
return blsKey.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyManager) Sign(addr address.Address, data []byte) (acrypto.Signature, error) {
|
|
||||||
ki, ok := k.keys[addr]
|
|
||||||
if !ok {
|
|
||||||
return acrypto.Signature{}, fmt.Errorf("unknown address %v", addr)
|
|
||||||
}
|
|
||||||
var sigType acrypto.SigType
|
|
||||||
if ki.Type == wallet.KTSecp256k1 {
|
|
||||||
sigType = acrypto.SigTypeBLS
|
|
||||||
hashed := blake2b.Sum256(data)
|
|
||||||
sig, err := crypto.Sign(ki.PrivateKey, hashed[:])
|
|
||||||
if err != nil {
|
|
||||||
return acrypto.Signature{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return acrypto.Signature{
|
|
||||||
Type: sigType,
|
|
||||||
Data: sig,
|
|
||||||
}, nil
|
|
||||||
} else if ki.Type == wallet.KTBLS {
|
|
||||||
panic("lotus validator cannot sign BLS messages")
|
|
||||||
} else {
|
|
||||||
panic("unknown signature type")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyManager) newSecp256k1Key() *wallet.Key {
|
|
||||||
randSrc := rand.New(rand.NewSource(k.secpSeed)) // nolint
|
|
||||||
prv, err := crypto.GenerateKeyFromSeed(randSrc)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
k.secpSeed++
|
|
||||||
key, err := wallet.NewKey(types.KeyInfo{
|
|
||||||
Type: wallet.KTSecp256k1,
|
|
||||||
PrivateKey: prv,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyManager) newBLSKey() *wallet.Key {
|
|
||||||
// FIXME: bls needs deterministic key generation
|
|
||||||
//sk := ffi.PrivateKeyGenerate(s.blsSeed)
|
|
||||||
// s.blsSeed++
|
|
||||||
sk := [32]byte{}
|
|
||||||
sk[0] = uint8(k.blsSeed) // hack to keep gas values determinist
|
|
||||||
k.blsSeed++
|
|
||||||
key, err := wallet.NewKey(types.KeyInfo{
|
|
||||||
Type: wallet.KTBLS,
|
|
||||||
PrivateKey: sk[:],
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
|
@ -1,217 +0,0 @@
|
|||||||
package validation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
"github.com/ipfs/go-datastore"
|
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
vstate "github.com/filecoin-project/chain-validation/state"
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ vstate.VMWrapper = &StateWrapper{}
|
|
||||||
|
|
||||||
type StateWrapper struct {
|
|
||||||
// The blockstore underlying the state tree and storage.
|
|
||||||
bs blockstore.Blockstore
|
|
||||||
|
|
||||||
ds datastore.Batching
|
|
||||||
// HAMT-CBOR store on top of the blockstore.
|
|
||||||
cst cbor.IpldStore
|
|
||||||
|
|
||||||
// CID of the root of the state tree.
|
|
||||||
stateRoot cid.Cid
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewState() *StateWrapper {
|
|
||||||
bs := blockstore.NewTemporary()
|
|
||||||
cst := cbor.NewCborStore(bs)
|
|
||||||
// Put EmptyObjectCid value in the store. When an actor is initially created its Head is set to this value.
|
|
||||||
_, err := cst.Put(context.TODO(), map[string]string{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
treeImpl, err := state.NewStateTree(cst)
|
|
||||||
if err != nil {
|
|
||||||
panic(err) // Never returns error, the error return should be removed.
|
|
||||||
}
|
|
||||||
root, err := treeImpl.Flush(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return &StateWrapper{
|
|
||||||
bs: bs,
|
|
||||||
ds: datastore.NewMapDatastore(),
|
|
||||||
cst: cst,
|
|
||||||
stateRoot: root,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateWrapper) NewVM() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateWrapper) Root() cid.Cid {
|
|
||||||
return s.stateRoot
|
|
||||||
}
|
|
||||||
|
|
||||||
// StoreGet the value at key from vm store
|
|
||||||
func (s *StateWrapper) StoreGet(key cid.Cid, out runtime.CBORUnmarshaler) error {
|
|
||||||
tree, err := state.LoadStateTree(s.cst, s.stateRoot)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tree.Store.Get(context.Background(), key, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StorePut `value` into vm store
|
|
||||||
func (s *StateWrapper) StorePut(value runtime.CBORMarshaler) (cid.Cid, error) {
|
|
||||||
tree, err := state.LoadStateTree(s.cst, s.stateRoot)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, err
|
|
||||||
}
|
|
||||||
return tree.Store.Put(context.Background(), value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateWrapper) Actor(addr address.Address) (vstate.Actor, error) {
|
|
||||||
tree, err := state.LoadStateTree(s.cst, s.stateRoot)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fcActor, err := tree.GetActor(addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &actorWrapper{*fcActor}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateWrapper) SetActorState(addr address.Address, balance abi.TokenAmount, actorState runtime.CBORMarshaler) (vstate.Actor, error) {
|
|
||||||
tree, err := state.LoadStateTree(s.cst, s.stateRoot)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// actor should exist
|
|
||||||
act, err := tree.GetActor(addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// add the state to the store and get a new head cid
|
|
||||||
actHead, err := tree.Store.Put(context.Background(), actorState)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// update the actor object with new head and balance parameter
|
|
||||||
actr := &actorWrapper{types.Actor{
|
|
||||||
Code: act.Code,
|
|
||||||
Nonce: act.Nonce,
|
|
||||||
// updates
|
|
||||||
Head: actHead,
|
|
||||||
Balance: balance,
|
|
||||||
}}
|
|
||||||
if err := tree.SetActor(addr, &actr.Actor); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return actr, s.flush(tree)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateWrapper) CreateActor(code cid.Cid, addr address.Address, balance abi.TokenAmount, actorState runtime.CBORMarshaler) (vstate.Actor, address.Address, error) {
|
|
||||||
idAddr := addr
|
|
||||||
tree, err := state.LoadStateTree(s.cst, s.stateRoot)
|
|
||||||
if err != nil {
|
|
||||||
return nil, address.Undef, err
|
|
||||||
}
|
|
||||||
if addr.Protocol() != address.ID {
|
|
||||||
|
|
||||||
actHead, err := tree.Store.Put(context.Background(), actorState)
|
|
||||||
if err != nil {
|
|
||||||
return nil, address.Undef, err
|
|
||||||
}
|
|
||||||
actr := &actorWrapper{types.Actor{
|
|
||||||
Code: code,
|
|
||||||
Head: actHead,
|
|
||||||
Balance: balance,
|
|
||||||
}}
|
|
||||||
|
|
||||||
idAddr, err = tree.RegisterNewAddress(addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, address.Undef, xerrors.Errorf("register new address for actor: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tree.SetActor(addr, &actr.Actor); err != nil {
|
|
||||||
return nil, address.Undef, xerrors.Errorf("setting new actor for actor: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// store newState
|
|
||||||
head, err := tree.Store.Put(context.Background(), actorState)
|
|
||||||
if err != nil {
|
|
||||||
return nil, address.Undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// create and store actor object
|
|
||||||
a := types.Actor{
|
|
||||||
Code: code,
|
|
||||||
Head: head,
|
|
||||||
Balance: balance,
|
|
||||||
}
|
|
||||||
if err := tree.SetActor(idAddr, &a); err != nil {
|
|
||||||
return nil, address.Undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &actorWrapper{a}, idAddr, s.flush(tree)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flushes a state tree to storage and sets this state's root to that tree's root CID.
|
|
||||||
func (s *StateWrapper) flush(tree *state.StateTree) (err error) {
|
|
||||||
s.stateRoot, err = tree.Flush(context.TODO())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Actor Wrapper
|
|
||||||
//
|
|
||||||
|
|
||||||
type actorWrapper struct {
|
|
||||||
types.Actor
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *actorWrapper) Code() cid.Cid {
|
|
||||||
return a.Actor.Code
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *actorWrapper) Head() cid.Cid {
|
|
||||||
return a.Actor.Head
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *actorWrapper) CallSeqNum() uint64 {
|
|
||||||
return a.Actor.Nonce
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *actorWrapper) Balance() big.Int {
|
|
||||||
return a.Actor.Balance
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Storage
|
|
||||||
//
|
|
||||||
|
|
||||||
type contextStore struct {
|
|
||||||
cbor.IpldStore
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *contextStore) Context() context.Context {
|
|
||||||
return s.ctx
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
package vm_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
suites "github.com/filecoin-project/chain-validation/suites"
|
|
||||||
|
|
||||||
factory "github.com/filecoin-project/lotus/chain/validation"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestSkipper contains a list of test cases skipped by the implementation.
|
|
||||||
type TestSkipper struct {
|
|
||||||
testSkips []suites.TestCase
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip return true if the sutire.TestCase should be skipped.
|
|
||||||
func (ts *TestSkipper) Skip(test suites.TestCase) bool {
|
|
||||||
for _, skip := range ts.testSkips {
|
|
||||||
if reflect.ValueOf(skip).Pointer() == reflect.ValueOf(test).Pointer() {
|
|
||||||
fmt.Printf("=== SKIP %v\n", runtime.FuncForPC(reflect.ValueOf(test).Pointer()).Name())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestSuiteSkips contains tests we wish to skip.
|
|
||||||
var TestSuiteSkipper TestSkipper
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// initialize the test skipper with tests being skipped
|
|
||||||
TestSuiteSkipper = TestSkipper{testSkips: []suites.TestCase{
|
|
||||||
// tests to skip go here
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChainValidationMessageSuite(t *testing.T) {
|
|
||||||
f := factory.NewFactories()
|
|
||||||
for _, testCase := range suites.MessageTestCases() {
|
|
||||||
testCase := testCase
|
|
||||||
if TestSuiteSkipper.Skip(testCase) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Run(caseName(testCase), func(t *testing.T) {
|
|
||||||
testCase(t, f)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChainValidationTipSetSuite(t *testing.T) {
|
|
||||||
f := factory.NewFactories()
|
|
||||||
for _, testCase := range suites.TipSetTestCases() {
|
|
||||||
testCase := testCase
|
|
||||||
if TestSuiteSkipper.Skip(testCase) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Run(caseName(testCase), func(t *testing.T) {
|
|
||||||
testCase(t, f)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func caseName(testCase suites.TestCase) string {
|
|
||||||
fqName := runtime.FuncForPC(reflect.ValueOf(testCase).Pointer()).Name()
|
|
||||||
toks := strings.Split(fqName, ".")
|
|
||||||
return toks[len(toks)-1]
|
|
||||||
}
|
|
1
go.mod
1
go.mod
@ -21,7 +21,6 @@ require (
|
|||||||
github.com/dustin/go-humanize v1.0.0
|
github.com/dustin/go-humanize v1.0.0
|
||||||
github.com/elastic/go-sysinfo v1.3.0
|
github.com/elastic/go-sysinfo v1.3.0
|
||||||
github.com/fatih/color v1.8.0
|
github.com/fatih/color v1.8.0
|
||||||
github.com/filecoin-project/chain-validation v0.0.6-0.20200813000554-40c22fe26eef
|
|
||||||
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d
|
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d
|
||||||
github.com/filecoin-project/go-address v0.0.3
|
github.com/filecoin-project/go-address v0.0.3
|
||||||
github.com/filecoin-project/go-bitfield v0.2.0
|
github.com/filecoin-project/go-bitfield v0.2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user