generate test-vectors based on tests from chain-validation project (#181)

* Read a subset of filecoin state over the full node API

* wip

* import export wip

* extract actors from message

* generate car for any state

* library for providing a pruned statetree

* test vector schema draft + example 'message' class test vector.

* message => messages test vector class.

* fixup

* wip

* use lb.NewBlockstore with ID

* fixup lotus-soup, and generate

* fix deals

* magic params

* work on schema / export of test vector

* fixup

* wip deserialise state tree

* pass at building a test case from a message

* progress loading / serializing

* recreation of ipld nodes

* generation of vector creates json

* kick off tvx tool.

* wip

* wip

* retain init actor state.

* initial test with printed out state

* remove testing.T, but keep require and assert libraries

* wip refactor state tree plucking.

* simplified

* removed factories

* remove builder.Build ; remove interface - use concrete iface

* comment out validateState

* remove Validator

* remove TestDriverBuilder

* remove client

* remove box

* remove gen

* remove factories

* remove KeyManager interfafce

* moved stuff around

* remove ValidationConfig

* extract randomness

* extract config and key_manager

* extract statewrapper

* extract applier

* rename factories to various

* flatten chain-validation package

* initial marshal of test vector

* do not require schema package

* fixup

* run all messages tests

* better names

* run all messages tests

* remove Indent setting from JSON encoder for now

* refactor, and actually running successfully ;-)

* remove irrelevant files; rename extract-msg command.

* remove root CID from state_tree object in schema.

* add tvx/lotus package; adjust .gitignore.

* tidy up command flag management.

* add comment.

* remove validateState and trackState

* remove xerrors

* remove NewVM

* remove commented out RootCID sets

* enable more tests

* add all `message_application` tests

* delete all.json

* update Message struct

* fix message serialization

* support multiple messages

* gofmt

* remove custom Message and SignedMessage types

* update tests with gzip and adhere to new schema for compressed CAR

* improved iface for Marshal

* update Validation

* remove test-suites and utils

* better names for chain. methods

* go mod tidy

* remove top-level dummyT

Co-authored-by: Will Scott <will@cypherpunk.email>
Co-authored-by: Raúl Kripalani <raul@protocol.ai>
This commit is contained in:
Anton Evangelatov 2020-08-05 19:40:09 +02:00 committed by GitHub
parent 17f0b4a2e1
commit 5353210814
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 3259 additions and 37 deletions

18
tvx/chain/account.go Normal file
View File

@ -0,0 +1,18 @@
package chain
import (
"github.com/filecoin-project/go-address"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) AccountConstructor(from, to address.Address, params *address.Address, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsAccount.Constructor, ser, opts...)
}
func (mp *MessageProducer) AccountPubkeyAddress(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsAccount.PubkeyAddress, ser, opts...)
}

56
tvx/chain/address.go Normal file
View File

@ -0,0 +1,56 @@
package chain
import (
"encoding/binary"
addr "github.com/filecoin-project/go-address"
"github.com/multiformats/go-varint"
)
// If you use this method while writing a test you are more than likely doing something wrong.
func MustNewIDAddr(id uint64) addr.Address {
address, err := addr.NewIDAddress(id)
if err != nil {
panic(err)
}
return address
}
func MustNewSECP256K1Addr(pubkey string) addr.Address {
// the pubkey of a secp256k1 address is hashed for consistent length.
address, err := addr.NewSecp256k1Address([]byte(pubkey))
if err != nil {
panic(err)
}
return address
}
func MustNewBLSAddr(seed int64) addr.Address {
buf := make([]byte, addr.BlsPublicKeyBytes)
binary.PutVarint(buf, seed)
address, err := addr.NewBLSAddress(buf)
if err != nil {
panic(err)
}
return address
}
func MustNewActorAddr(data string) addr.Address {
address, err := addr.NewActorAddress([]byte(data))
if err != nil {
panic(err)
}
return address
}
func MustIdFromAddress(a addr.Address) uint64 {
if a.Protocol() != addr.ID {
panic("must be ID protocol address")
}
id, _, err := varint.FromUvarint(a.Payload())
if err != nil {
panic(err)
}
return id
}

19
tvx/chain/cron.go Normal file
View File

@ -0,0 +1,19 @@
package chain
import (
"github.com/filecoin-project/go-address"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) CronConstructor(from, to address.Address, params *cron.ConstructorParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsCron.Constructor, ser, opts...)
}
func (mp *MessageProducer) CronEpochTick(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsCron.EpochTick, ser, opts...)
}

18
tvx/chain/init_.go Normal file
View File

@ -0,0 +1,18 @@
package chain
import (
"github.com/filecoin-project/go-address"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) InitConstructor(from, to address.Address, params *init_.ConstructorParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsInit.Constructor, ser, opts...)
}
func (mp *MessageProducer) InitExec(from, to address.Address, params *init_.ExecParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsInit.Exec, ser, opts...)
}

47
tvx/chain/market.go Normal file
View File

@ -0,0 +1,47 @@
package chain
import (
"github.com/filecoin-project/go-address"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) MarketConstructor(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.Constructor, ser, opts...)
}
func (mp *MessageProducer) MarketAddBalance(from, to address.Address, params *address.Address, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.AddBalance, ser, opts...)
}
func (mp *MessageProducer) MarketWithdrawBalance(from, to address.Address, params *market.WithdrawBalanceParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.WithdrawBalance, ser, opts...)
}
func (mp *MessageProducer) MarketPublishStorageDeals(from, to address.Address, params *market.PublishStorageDealsParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.PublishStorageDeals, ser, opts...)
}
func (mp *MessageProducer) MarketVerifyDealsForActivation(from, to address.Address, params *market.VerifyDealsForActivationParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.VerifyDealsForActivation, ser, opts...)
}
func (mp *MessageProducer) MarketActivateDeals(from, to address.Address, params *market.ActivateDealsParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.ActivateDeals, ser, opts...)
}
func (mp *MessageProducer) MarketOnMinerSectorsTerminate(from, to address.Address, params *market.OnMinerSectorsTerminateParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.OnMinerSectorsTerminate, ser, opts...)
}
func (mp *MessageProducer) MarketComputeDataCommitment(from, to address.Address, params *market.ComputeDataCommitmentParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.ComputeDataCommitment, ser, opts...)
}
func (mp *MessageProducer) MarketCronTick(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMarket.CronTick, ser, opts...)
}

View File

@ -0,0 +1,94 @@
package chain
import (
address "github.com/filecoin-project/go-address"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
big_spec "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/lotus/chain/types"
)
// The created messages are retained for subsequent export or evaluation in a VM.
type MessageProducer struct {
defaults msgOpts // Note non-pointer reference.
messages []*types.Message
}
// NewMessageProducer creates a new message producer, delegating message creation to `factory`.
func NewMessageProducer(defaultGasLimit int64, defaultGasPrice big_spec.Int) *MessageProducer {
return &MessageProducer{
defaults: msgOpts{
value: big_spec.Zero(),
gasLimit: defaultGasLimit,
gasPrice: defaultGasPrice,
},
}
}
// Messages returns a slice containing all messages created by the producer.
func (mp *MessageProducer) Messages() []*types.Message {
return mp.messages
}
// BuildFull creates and returns a single message.
func (mp *MessageProducer) BuildFull(from, to address.Address, method abi_spec.MethodNum, nonce uint64, value, gasPrice big_spec.Int, gasLimit int64, params []byte) *types.Message {
fm := &types.Message{
To: to,
From: from,
Nonce: nonce,
Value: value,
Method: method,
Params: params,
GasPrice: gasPrice,
GasLimit: gasLimit,
}
mp.messages = append(mp.messages, fm)
return fm
}
// Build creates and returns a single message, using default gas parameters unless modified by `opts`.
func (mp *MessageProducer) Build(from, to address.Address, method abi_spec.MethodNum, params []byte, opts ...MsgOpt) *types.Message {
values := mp.defaults
for _, opt := range opts {
opt(&values)
}
return mp.BuildFull(from, to, method, values.nonce, values.value, values.gasPrice, values.gasLimit, params)
}
// msgOpts specifies value and gas parameters for a message, supporting a functional options pattern
// for concise but customizable message construction.
type msgOpts struct {
nonce uint64
value big_spec.Int
gasPrice big_spec.Int
gasLimit int64
}
// MsgOpt is an option configuring message value or gas parameters.
type MsgOpt func(*msgOpts)
func Value(value big_spec.Int) MsgOpt {
return func(opts *msgOpts) {
opts.value = value
}
}
func Nonce(n uint64) MsgOpt {
return func(opts *msgOpts) {
opts.nonce = n
}
}
func GasLimit(limit int64) MsgOpt {
return func(opts *msgOpts) {
opts.gasLimit = limit
}
}
func GasPrice(price int64) MsgOpt {
return func(opts *msgOpts) {
opts.gasPrice = big_spec.NewInt(price)
}
}

85
tvx/chain/miner.go Normal file
View File

@ -0,0 +1,85 @@
package chain
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi/big"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) MinerConstructor(from, to address.Address, params *power.MinerConstructorParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.Constructor, ser, opts...)
}
func (mp *MessageProducer) MinerControlAddresses(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ControlAddresses, ser, opts...)
}
func (mp *MessageProducer) MinerChangeWorkerAddress(from, to address.Address, params *miner.ChangeWorkerAddressParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ChangeWorkerAddress, ser, opts...)
}
func (mp *MessageProducer) MinerChangePeerID(from, to address.Address, params *miner.ChangePeerIDParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ChangePeerID, ser, opts...)
}
func (mp *MessageProducer) MinerSubmitWindowedPoSt(from, to address.Address, params *miner.SubmitWindowedPoStParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.SubmitWindowedPoSt, ser, opts...)
}
func (mp *MessageProducer) MinerPreCommitSector(from, to address.Address, params *miner.SectorPreCommitInfo, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.PreCommitSector, ser, opts...)
}
func (mp *MessageProducer) MinerProveCommitSector(from, to address.Address, params *miner.ProveCommitSectorParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ProveCommitSector, ser, opts...)
}
func (mp *MessageProducer) MinerExtendSectorExpiration(from, to address.Address, params *miner.ExtendSectorExpirationParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ExtendSectorExpiration, ser, opts...)
}
func (mp *MessageProducer) MinerTerminateSectors(from, to address.Address, params *miner.TerminateSectorsParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.TerminateSectors, ser, opts...)
}
func (mp *MessageProducer) MinerDeclareFaults(from, to address.Address, params *miner.DeclareFaultsParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.DeclareFaults, ser, opts...)
}
func (mp *MessageProducer) MinerDeclareFaultsRecovered(from, to address.Address, params *miner.DeclareFaultsRecoveredParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.DeclareFaultsRecovered, ser, opts...)
}
func (mp *MessageProducer) MinerOnDeferredCronEvent(from, to address.Address, params *miner.CronEventPayload, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.OnDeferredCronEvent, ser, opts...)
}
func (mp *MessageProducer) MinerCheckSectorProven(from, to address.Address, params *miner.CheckSectorProvenParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.CheckSectorProven, ser, opts...)
}
func (mp *MessageProducer) MinerAddLockedFund(from, to address.Address, params *big.Int, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.AddLockedFund, ser, opts...)
}
func (mp *MessageProducer) MinerReportConsensusFault(from, to address.Address, params *miner.ReportConsensusFaultParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ReportConsensusFault, ser, opts...)
}
func (mp *MessageProducer) MinerWithdrawBalance(from, to address.Address, params *miner.WithdrawBalanceParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.WithdrawBalance, ser, opts...)
}
func (mp *MessageProducer) MinerConfirmSectorProofsValid(from, to address.Address, params *builtin_spec.ConfirmSectorProofsParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ConfirmSectorProofsValid, ser, opts...)
}
func (mp *MessageProducer) MinerChangeMultiaddrs(from, to address.Address, params *miner.ChangeMultiaddrsParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMiner.ChangeMultiaddrs, ser, opts...)
}

42
tvx/chain/multisig.go Normal file
View File

@ -0,0 +1,42 @@
package chain
import (
"github.com/filecoin-project/go-address"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
multisig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) MultisigConstructor(from, to address.Address, params *multisig.ConstructorParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.Constructor, ser, opts...)
}
func (mp *MessageProducer) MultisigPropose(from, to address.Address, params *multisig.ProposeParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.Propose, ser, opts...)
}
func (mp *MessageProducer) MultisigApprove(from, to address.Address, params *multisig.TxnIDParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.Approve, ser, opts...)
}
func (mp *MessageProducer) MultisigCancel(from, to address.Address, params *multisig.TxnIDParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.Cancel, ser, opts...)
}
func (mp *MessageProducer) MultisigAddSigner(from, to address.Address, params *multisig.AddSignerParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.AddSigner, ser, opts...)
}
func (mp *MessageProducer) MultisigRemoveSigner(from, to address.Address, params *multisig.RemoveSignerParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.RemoveSigner, ser, opts...)
}
func (mp *MessageProducer) MultisigSwapSigner(from, to address.Address, params *multisig.SwapSignerParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.SwapSigner, ser, opts...)
}
func (mp *MessageProducer) MultisigChangeNumApprovalsThreshold(from, to address.Address, params *multisig.ChangeNumApprovalsThresholdParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsMultisig.ChangeNumApprovalsThreshold, ser, opts...)
}

27
tvx/chain/paych.go Normal file
View File

@ -0,0 +1,27 @@
package chain
import (
"github.com/filecoin-project/go-address"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) PaychConstructor(from, to address.Address, params *paych.ConstructorParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPaych.Constructor, ser, opts...)
}
func (mp *MessageProducer) PaychUpdateChannelState(from, to address.Address, params *paych.UpdateChannelStateParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPaych.UpdateChannelState, ser, opts...)
}
func (mp *MessageProducer) PaychSettle(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPaych.Settle, ser, opts...)
}
func (mp *MessageProducer) PaychCollect(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPaych.Collect, ser, opts...)
}

49
tvx/chain/power.go Normal file
View File

@ -0,0 +1,49 @@
package chain
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) PowerConstructor(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.Constructor, ser, opts...)
}
func (mp *MessageProducer) PowerCreateMiner(from, to address.Address, params *power.CreateMinerParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.CreateMiner, ser, opts...)
}
func (mp *MessageProducer) PowerUpdateClaimedPower(from, to address.Address, params *power.UpdateClaimedPowerParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.UpdateClaimedPower, ser, opts...)
}
func (mp *MessageProducer) PowerEnrollCronEvent(from, to address.Address, params *power.EnrollCronEventParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.EnrollCronEvent, ser, opts...)
}
func (mp *MessageProducer) PowerOnEpochTickEnd(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.OnEpochTickEnd, ser, opts...)
}
func (mp *MessageProducer) PowerUpdatePledgeTotal(from, to address.Address, params *big.Int, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.UpdatePledgeTotal, ser, opts...)
}
func (mp *MessageProducer) PowerOnConsensusFault(from, to address.Address, params *big.Int, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.OnConsensusFault, ser, opts...)
}
func (mp *MessageProducer) PowerSubmitPoRepForBulkVerify(from, to address.Address, params *abi.SealVerifyInfo, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.SubmitPoRepForBulkVerify, ser, opts...)
}
func (mp *MessageProducer) PowerCurrentTotalPower(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsPower.CurrentTotalPower, ser, opts...)
}

18
tvx/chain/puppet.go Normal file
View File

@ -0,0 +1,18 @@
package chain
import (
"github.com/filecoin-project/go-address"
puppet "github.com/filecoin-project/specs-actors/actors/puppet"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) PuppetConstructor(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, puppet.MethodsPuppet.Constructor, ser, opts...)
}
func (mp *MessageProducer) PuppetSend(from, to address.Address, params *puppet.SendParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, puppet.MethodsPuppet.Send, ser, opts...)
}

28
tvx/chain/reward.go Normal file
View File

@ -0,0 +1,28 @@
package chain
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi/big"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func (mp *MessageProducer) RewardConstructor(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsReward.Constructor, ser, opts...)
}
func (mp *MessageProducer) RewardAwardBlockReward(from, to address.Address, params *reward.AwardBlockRewardParams, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsReward.AwardBlockReward, ser, opts...)
}
func (mp *MessageProducer) RewardLastPerEpochReward(from, to address.Address, params *adt.EmptyValue, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsReward.ThisEpochReward, ser, opts...)
}
func (mp *MessageProducer) RewardUpdateNetworkKPI(from, to address.Address, params *big.Int, opts ...MsgOpt) *types.Message {
ser := MustSerialize(params)
return mp.Build(from, to, builtin_spec.MethodsReward.UpdateNetworkKPI, ser, opts...)
}

View File

@ -0,0 +1,38 @@
package chain
import (
"bytes"
"fmt"
cbg "github.com/whyrusleeping/cbor-gen"
)
func MustSerialize(i cbg.CBORMarshaler) []byte {
out, err := Serialize(i)
if err != nil {
panic(err)
}
return out
}
func Serialize(i cbg.CBORMarshaler) ([]byte, error) {
buf := new(bytes.Buffer)
if err := i.MarshalCBOR(buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func MustDeserialize(b []byte, out interface{}) {
if err := Deserialize(b, out); err != nil {
panic(err)
}
}
func Deserialize(b []byte, out interface{}) error {
um, ok := out.(cbg.CBORUnmarshaler)
if !ok {
return fmt.Errorf("type %T does not implement UnmarshalCBOR", out)
}
return um.UnmarshalCBOR(bytes.NewReader(b))
}

52
tvx/chain/sugar.go Normal file
View File

@ -0,0 +1,52 @@
package chain
import (
"github.com/filecoin-project/go-address"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
init_spec "github.com/filecoin-project/specs-actors/actors/builtin/init"
multisig_spec "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
paych_spec "github.com/filecoin-project/specs-actors/actors/builtin/paych"
power_spec "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/lotus/chain/types"
)
var noParams []byte
// Transfer builds a simple value transfer message and returns it.
func (mp *MessageProducer) Transfer(from, to address.Address, opts ...MsgOpt) *types.Message {
return mp.Build(from, to, builtin_spec.MethodSend, noParams, opts...)
}
func (mp *MessageProducer) CreatePaymentChannelActor(from, to address.Address, opts ...MsgOpt) *types.Message {
return mp.InitExec(from, builtin_spec.InitActorAddr, &init_spec.ExecParams{
CodeCID: builtin_spec.PaymentChannelActorCodeID,
ConstructorParams: MustSerialize(&paych_spec.ConstructorParams{
From: from,
To: to,
}),
}, opts...)
}
func (mp *MessageProducer) CreateMultisigActor(from address.Address, signers []address.Address, unlockDuration abi_spec.ChainEpoch, numApprovals uint64, opts ...MsgOpt) *types.Message {
return mp.InitExec(from, builtin_spec.InitActorAddr, &init_spec.ExecParams{
CodeCID: builtin_spec.MultisigActorCodeID,
ConstructorParams: MustSerialize(&multisig_spec.ConstructorParams{
Signers: signers,
NumApprovalsThreshold: numApprovals,
UnlockDuration: unlockDuration,
}),
}, opts...)
}
func (mp *MessageProducer) CreateMinerActor(owner, worker address.Address, sealProofType abi_spec.RegisteredSealProof, pid peer.ID, maddrs []abi_spec.Multiaddrs, opts ...MsgOpt) *types.Message {
return mp.PowerCreateMiner(owner, builtin_spec.StoragePowerActorAddr, &power_spec.CreateMinerParams{
Worker: worker,
Owner: owner,
SealProofType: sealProofType,
Peer: abi_spec.PeerID(pid),
Multiaddrs: maddrs,
}, opts...)
}

14
tvx/chain/types/block.go Normal file
View File

@ -0,0 +1,14 @@
package types
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
)
// BlockMessagesInfo contains messages for one block in a tipset.
type BlockMessagesInfo struct {
BLSMessages []*types.Message
SECPMessages []*types.SignedMessage
Miner address.Address
TicketCount int64
}

View File

@ -0,0 +1,17 @@
package types
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
)
// ExecutionContext provides the context for execution of a message.
type ExecutionContext struct {
Epoch abi.ChainEpoch // The epoch number ("height") during which a message is executed.
Miner address.Address // The miner actor which earns gas fees from message execution.
}
// NewExecutionContext builds a new execution context.
func NewExecutionContext(epoch int64, miner address.Address) *ExecutionContext {
return &ExecutionContext{abi.ChainEpoch(epoch), miner}
}

View File

@ -0,0 +1,20 @@
package types
import (
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
)
// MessageReceipt is the return value of message application.
type MessageReceipt struct {
ExitCode exitcode.ExitCode
ReturnValue []byte
GasUsed GasUnits
}
type GasUnits int64
func (gu GasUnits) Big() big.Int {
return big.NewInt(int64(gu))
}

View File

@ -0,0 +1,64 @@
package types
import (
"fmt"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid"
)
type Trackable interface {
GoSyntax() string
GoContainer() string
}
var _ Trackable = (*ApplyMessageResult)(nil)
var _ Trackable = (*ApplyTipSetResult)(nil)
type ApplyMessageResult struct {
Receipt MessageReceipt
Penalty abi.TokenAmount
Reward abi.TokenAmount
Root string
}
func (mr ApplyMessageResult) GoSyntax() string {
return fmt.Sprintf("types.ApplyMessageResult{Receipt: %#v, Penalty: abi.NewTokenAmount(%d), Reward: abi.NewTokenAmount(%d), Root: \"%s\"}", mr.Receipt, mr.Penalty, mr.Reward, mr.Root)
}
func (mr ApplyMessageResult) GoContainer() string {
return "[]types.ApplyMessageResult"
}
func (mr ApplyMessageResult) StateRoot() cid.Cid {
root, err := cid.Decode(mr.Root)
if err != nil {
panic(err)
}
return root
}
func (mr ApplyMessageResult) GasUsed() GasUnits {
return mr.Receipt.GasUsed
}
type ApplyTipSetResult struct {
Receipts []MessageReceipt
Root string
}
func (tr ApplyTipSetResult) GoSyntax() string {
return fmt.Sprintf("%#v", tr)
}
func (tr ApplyTipSetResult) GoContainer() string {
return "[]types.ApplyTipSetResult"
}
func (tr ApplyTipSetResult) StateRoot() cid.Cid {
root, err := cid.Decode(tr.Root)
if err != nil {
panic(err)
}
return root
}

View File

@ -0,0 +1,15 @@
package types
import (
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/ipfs/go-cid"
)
type PreSeal struct {
CommR cid.Cid
CommD cid.Cid
SectorID abi.SectorNumber
Deal market.DealProposal
ProofType abi.RegisteredProof
}

52
tvx/chain/wallet/bls.go Normal file
View File

@ -0,0 +1,52 @@
package wallet
import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/crypto"
ffi "github.com/filecoin-project/filecoin-ffi"
)
type blsSigner struct{}
func (blsSigner) GenPrivate() ([]byte, error) {
pk := ffi.PrivateKeyGenerate()
return pk[:], nil
}
func (blsSigner) ToPublic(priv []byte) ([]byte, error) {
var pk ffi.PrivateKey
copy(pk[:], priv)
pub := ffi.PrivateKeyPublicKey(pk)
return pub[:], nil
}
func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) {
var pk ffi.PrivateKey
copy(pk[:], p)
sig := ffi.PrivateKeySign(pk, msg)
return sig[:], nil
}
func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error {
digests := []ffi.Digest{ffi.Hash(ffi.Message(msg))}
var pubk ffi.PublicKey
copy(pubk[:], a.Payload())
pubkeys := []ffi.PublicKey{pubk}
var s ffi.Signature
copy(s[:], sig)
if !ffi.Verify(&s, digests, pubkeys) {
return fmt.Errorf("bls signature failed to verify")
}
return nil
}
func init() {
RegisterSignature(crypto.SigTypeBLS, blsSigner{})
}

57
tvx/chain/wallet/secp.go Normal file
View File

@ -0,0 +1,57 @@
package wallet
import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
crypto2 "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/minio/blake2b-simd"
)
type secpSigner struct{}
func (secpSigner) GenPrivate() ([]byte, error) {
priv, err := crypto.GenerateKey()
if err != nil {
return nil, err
}
return priv, nil
}
func (secpSigner) ToPublic(pk []byte) ([]byte, error) {
return crypto.PublicKey(pk), nil
}
func (secpSigner) Sign(pk []byte, msg []byte) ([]byte, error) {
b2sum := blake2b.Sum256(msg)
sig, err := crypto.Sign(pk, b2sum[:])
if err != nil {
return nil, err
}
return sig, nil
}
func (secpSigner) Verify(sig []byte, a address.Address, msg []byte) error {
b2sum := blake2b.Sum256(msg)
pubk, err := crypto.EcRecover(b2sum[:], sig)
if err != nil {
return err
}
maybeaddr, err := address.NewSecp256k1Address(pubk)
if err != nil {
return err
}
if a != maybeaddr {
return fmt.Errorf("signature did not match")
}
return nil
}
func init() {
RegisterSignature(crypto2.SigTypeSecp256k1, secpSigner{})
}

113
tvx/chain/wallet/wallet.go Normal file
View File

@ -0,0 +1,113 @@
package wallet
import (
"errors"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/ipsn/go-secp256k1"
blake2b "github.com/minio/blake2b-simd"
bls "github.com/filecoin-project/filecoin-ffi"
)
// KeyInfo is used for storing keys in KeyStore
type KeyInfo struct {
Type crypto.SigType
PrivateKey []byte
}
type Key struct {
KeyInfo
PublicKey []byte
Address address.Address
}
func NewKey(keyinfo KeyInfo) (*Key, error) {
k := &Key{
KeyInfo: keyinfo,
}
var err error
k.PublicKey, err = ToPublic(k.Type, k.PrivateKey)
if err != nil {
return nil, err
}
switch k.Type {
case crypto.SigTypeSecp256k1:
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
if err != nil {
return nil, fmt.Errorf("converting Secp256k1 to address: %w", err)
}
case crypto.SigTypeBLS:
k.Address, err = address.NewBLSAddress(k.PublicKey)
if err != nil {
return nil, fmt.Errorf("converting BLS to address: %w", err)
}
default:
return nil, errors.New("unknown key type")
}
return k, nil
}
func Sign(data []byte, secretKey []byte, sigtype crypto.SigType) (crypto.Signature, error) {
var signature []byte
var err error
if sigtype == crypto.SigTypeSecp256k1 {
hash := blake2b.Sum256(data)
signature, err = SignSecp(secretKey, hash[:])
} else if sigtype == crypto.SigTypeBLS {
signature, err = SignBLS(secretKey, data)
} else {
err = fmt.Errorf("unknown signature type %d", sigtype)
}
return crypto.Signature{
Type: sigtype,
Data: signature,
}, err
}
func SignSecp(sk, msg []byte) ([]byte, error) {
return secp256k1.Sign(msg, sk)
}
// SignBLS signs the given message with BLS.
func SignBLS(sk, msg []byte) ([]byte, error) {
var privateKey bls.PrivateKey
copy(privateKey[:], sk)
sig := bls.PrivateKeySign(privateKey, msg)
return sig[:], nil
}
// ported from lotus
// SigShim is used for introducing signature functions
type SigShim interface {
GenPrivate() ([]byte, error)
ToPublic(pk []byte) ([]byte, error)
Sign(pk []byte, msg []byte) ([]byte, error)
Verify(sig []byte, a address.Address, msg []byte) error
}
var sigs map[crypto.SigType]SigShim
// RegisterSig should be only used during init
func RegisterSignature(typ crypto.SigType, vs SigShim) {
if sigs == nil {
sigs = make(map[crypto.SigType]SigShim)
}
sigs[typ] = vs
}
// ToPublic converts private key to public key
func ToPublic(sigType crypto.SigType, pk []byte) ([]byte, error) {
sv, ok := sigs[sigType]
if !ok {
return nil, fmt.Errorf("cannot generate public key of unsupported type: %v", sigType)
}
return sv.ToPublic(pk)
}

150
tvx/drivers/applier.go Normal file
View File

@ -0,0 +1,150 @@
package drivers
import (
"context"
"errors"
acrypto "github.com/filecoin-project/specs-actors/actors/crypto"
"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/puppet"
"github.com/ipfs/go-cid"
"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"
vtypes "github.com/filecoin-project/oni/tvx/chain/types"
)
// Applier applies messages to state trees and storage.
type Applier struct {
stateWrapper *StateWrapper
syscalls vm.SyscallBuilder
}
func NewApplier(sw *StateWrapper, syscalls vm.SyscallBuilder) *Applier {
return &Applier{sw, syscalls}
}
func (a *Applier) ApplyMessage(epoch abi.ChainEpoch, lm *types.Message) (vtypes.ApplyMessageResult, error) {
receipt, penalty, reward, err := a.applyMessage(epoch, lm)
return vtypes.ApplyMessageResult{
Receipt: receipt,
Penalty: penalty,
Reward: reward,
Root: a.stateWrapper.Root().String(),
}, err
}
func (a *Applier) ApplySignedMessage(epoch abi.ChainEpoch, msg *types.SignedMessage) (vtypes.ApplyMessageResult, error) {
var lm types.ChainMsg
switch msg.Signature.Type {
case acrypto.SigTypeSecp256k1:
lm = msg
case acrypto.SigTypeBLS:
lm = &msg.Message
default:
return vtypes.ApplyMessageResult{}, errors.New("Unknown signature type")
}
// TODO: Validate the sig first
receipt, penalty, reward, err := a.applyMessage(epoch, lm)
return vtypes.ApplyMessageResult{
Receipt: receipt,
Penalty: penalty,
Reward: reward,
Root: a.stateWrapper.Root().String(),
}, err
}
func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.BlockMessagesInfo, rnd RandomnessSource) (vtypes.ApplyTipSetResult, error) {
cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls)
sm := stmgr.NewStateManager(cs)
var bms []stmgr.BlockMessages
for _, b := range blocks {
bm := stmgr.BlockMessages{
Miner: b.Miner,
WinCount: 1,
}
for _, m := range b.BLSMessages {
bm.BlsMessages = append(bm.BlsMessages, m)
}
for _, m := range b.SECPMessages {
bm.SecpkMessages = append(bm.SecpkMessages, m)
}
bms = append(bms, bm)
}
var receipts []vtypes.MessageReceipt
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
})
if err != nil {
return vtypes.ApplyTipSetResult{}, err
}
a.stateWrapper.stateRoot = sroot
return vtypes.ApplyTipSetResult{
Receipts: receipts,
Root: a.stateWrapper.Root().String(),
}, nil
}
func (a *Applier) applyMessage(epoch abi.ChainEpoch, lm types.ChainMsg) (vtypes.MessageReceipt, abi.TokenAmount, abi.TokenAmount, error) {
ctx := context.TODO()
base := a.stateWrapper.Root()
lotusVM, err := vm.NewVM(base, epoch, &vmRand{}, a.stateWrapper.bs, a.syscalls, nil)
// 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
}

21
tvx/drivers/config.go Normal file
View File

@ -0,0 +1,21 @@
package drivers
type Config struct {
checkExitCode bool
checkReturnValue bool
}
func NewConfig(exit, ret bool) *Config {
return &Config{
checkExitCode: exit,
checkReturnValue: ret,
}
}
func (v Config) ValidateExitCode() bool {
return v.checkExitCode
}
func (v Config) ValidateReturnValue() bool {
return v.checkReturnValue
}

View File

@ -0,0 +1,28 @@
package drivers
import (
"fmt"
"os"
)
var t dummyTestingT
type dummyTestingT struct{}
func (d dummyTestingT) FailNow() {
panic("fail now")
}
func (d dummyTestingT) Errorf(format string, args ...interface{}) {
fmt.Printf(format, args)
os.Exit(1)
}
func (d dummyTestingT) Fatalf(format string, args ...interface{}) {
d.Errorf(format, args)
}
func (d dummyTestingT) Fatal(args ...interface{}) {
fmt.Println(args)
os.Exit(1)
}

105
tvx/drivers/key_manager.go Normal file
View File

@ -0,0 +1,105 @@
package drivers
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/wallet"
"github.com/filecoin-project/lotus/chain/types"
)
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))
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
}

View File

@ -0,0 +1,64 @@
package drivers
import (
"encoding/binary"
"testing"
"github.com/filecoin-project/go-address"
commcid "github.com/filecoin-project/go-fil-commcid"
"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/market"
"github.com/filecoin-project/oni/tvx/chain/types"
)
type MockSectorBuilder struct {
t testing.TB
sectorSeq uint64
// PreSeal is intexted by sectorID
MinerSectors map[address.Address][]*types.PreSeal
}
func NewMockSectorBuilder(t testing.TB) *MockSectorBuilder {
return &MockSectorBuilder{
t: t,
sectorSeq: 0,
MinerSectors: make(map[address.Address][]*types.PreSeal),
}
}
func (msb *MockSectorBuilder) NewPreSealedSector(miner, client address.Address, pt abi.RegisteredProof, ssize abi.SectorSize, start, end abi.ChainEpoch) *types.PreSeal {
minerSectors := msb.MinerSectors[miner]
sectorID := len(minerSectors)
token := make([]byte, 32)
binary.PutUvarint(token, msb.sectorSeq)
// the only error we could get is if token isn't 32 long, ignore
D, _ := commcid.DataCommitmentV1ToCID(token)
R, _ := commcid.ReplicaCommitmentV1ToCID(token)
msb.sectorSeq++
preseal := &types.PreSeal{
CommR: R,
CommD: D,
SectorID: abi.SectorNumber(sectorID),
Deal: market.DealProposal{
PieceCID: D,
PieceSize: abi.PaddedPieceSize(ssize),
Client: client,
Provider: miner,
StartEpoch: start,
EndEpoch: end,
// TODO how do we want to interact with these values?
StoragePricePerEpoch: big.Zero(),
ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(),
},
ProofType: pt,
}
msb.MinerSectors[miner] = append(msb.MinerSectors[miner], preseal)
return preseal
}

44
tvx/drivers/randomness.go Normal file
View File

@ -0,0 +1,44 @@
package drivers
import (
"context"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
acrypto "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/abi"
)
// RandomnessSource provides randomness to actors.
type RandomnessSource interface {
Randomness(ctx context.Context, tag acrypto.DomainSeparationTag, epoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
}
// Specifies a domain for randomness generation.
type RandomnessType int
type randWrapper struct {
rnd RandomnessSource
}
func (w *randWrapper) GetRandomness(ctx context.Context, pers acrypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return w.rnd.Randomness(ctx, pers, round, entropy)
}
type vmRand struct {
}
func (*vmRand) GetRandomness(ctx context.Context, dst acrypto.DomainSeparationTag, h abi.ChainEpoch, input []byte) ([]byte, error) {
panic("implement me")
}
type fakeRandSrc struct {
}
func (r fakeRandSrc) Randomness(_ context.Context, _ acrypto.DomainSeparationTag, _ abi_spec.ChainEpoch, _ []byte) (abi_spec.Randomness, error) {
return abi_spec.Randomness("sausages"), nil
}
func NewRandomnessSource() RandomnessSource {
return &fakeRandSrc{}
}

206
tvx/drivers/state_driver.go Normal file
View File

@ -0,0 +1,206 @@
package drivers
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/oni/tvx/chain"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
big_spec "github.com/filecoin-project/specs-actors/actors/abi/big"
miner_spec "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power_spec "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/runtime"
adt_spec "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
"github.com/stretchr/testify/require"
cbg "github.com/whyrusleeping/cbor-gen"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
account_spec "github.com/filecoin-project/specs-actors/actors/builtin/account"
)
var (
SECP = address.SECP256K1
BLS = address.BLS
)
// StateDriver mutates and inspects a state.
type StateDriver struct {
st *StateWrapper
w *KeyManager
rs RandomnessSource
minerInfo *MinerInfo
// Mapping for IDAddresses to their pubkey/actor addresses. Used for lookup when signing messages.
actorIDMap map[address.Address]address.Address
}
// info about the state drivers builtin miner
type MinerInfo struct {
Owner address.Address
OwnerID address.Address
Worker address.Address
WorkerID address.Address
}
// NewStateDriver creates a new state driver for a state.
func NewStateDriver(st *StateWrapper, w *KeyManager) *StateDriver {
return &StateDriver{st, w, NewRandomnessSource(), nil, make(map[address.Address]address.Address)}
}
// State returns the state.
func (d *StateDriver) State() *StateWrapper {
return d.st
}
func (d *StateDriver) Wallet() *KeyManager {
return d.w
}
func (d *StateDriver) Randomness() RandomnessSource {
return d.rs
}
func (d *StateDriver) GetState(c cid.Cid, out cbg.CBORUnmarshaler) {
err := d.st.StoreGet(c, out)
require.NoError(t, err)
}
func (d *StateDriver) PutState(in cbg.CBORMarshaler) cid.Cid {
c, err := d.st.StorePut(in)
require.NoError(t, err)
return c
}
func (d *StateDriver) GetActorState(actorAddr address.Address, out cbg.CBORUnmarshaler) {
actor, err := d.State().Actor(actorAddr)
require.NoError(t, err)
require.NotNil(t, actor)
d.GetState(actor.Head(), out)
}
// NewAccountActor installs a new account actor, returning the address.
func (d *StateDriver) NewAccountActor(addrType address.Protocol, balanceAttoFil abi_spec.TokenAmount) (pubkey address.Address, id address.Address) {
var addr address.Address
switch addrType {
case address.SECP256K1:
addr = d.w.NewSECP256k1AccountAddress()
case address.BLS:
addr = d.w.NewBLSAccountAddress()
default:
require.FailNowf(t, "unsupported address", "protocol for account actor: %v", addrType)
}
_, idAddr, err := d.st.CreateActor(builtin_spec.AccountActorCodeID, addr, balanceAttoFil, &account_spec.State{Address: addr})
require.NoError(t, err)
d.actorIDMap[idAddr] = addr
return addr, idAddr
}
func (d *StateDriver) ActorPubKey(idAddress address.Address) address.Address {
if idAddress.Protocol() != address.ID {
t.Fatalf("ActorPubKey methods expects ID protocol address. actual: %v", idAddress.Protocol())
}
pubkeyAddr, found := d.actorIDMap[idAddress]
if !found {
t.Fatalf("Failed to find pubkey address for: %s", idAddress)
}
return pubkeyAddr
}
func (d *StateDriver) BuiltinMinerInfo() *MinerInfo {
return d.minerInfo
}
// create miner without sending a message. modify the init and power actor manually
func (d *StateDriver) newMinerAccountActor(sealProofType abi_spec.RegisteredSealProof, periodBoundary abi_spec.ChainEpoch) address.Address {
// creat a miner, owner, and its worker
minerOwnerPk, minerOwnerID := d.NewAccountActor(address.SECP256K1, big_spec.NewInt(1_000_000_000))
minerWorkerPk, minerWorkerID := d.NewAccountActor(address.BLS, big_spec.Zero())
expectedMinerActorIDAddress := chain.MustNewIDAddr(chain.MustIdFromAddress(minerWorkerID) + 1)
minerActorAddrs := computeInitActorExecReturn(minerWorkerPk, 0, 1, expectedMinerActorIDAddress)
d.minerInfo = &MinerInfo{
Owner: minerOwnerPk,
OwnerID: minerOwnerID,
Worker: minerWorkerPk,
WorkerID: minerWorkerID,
}
ss, err := sealProofType.SectorSize()
require.NoError(t, err)
ps, err := sealProofType.WindowPoStPartitionSectors()
require.NoError(t, err)
mi := &miner_spec.MinerInfo{
Owner: minerOwnerID,
Worker: minerWorkerID,
PendingWorkerKey: nil,
PeerId: abi_spec.PeerID("chain-validation"),
Multiaddrs: nil,
SealProofType: sealProofType,
SectorSize: ss,
WindowPoStPartitionSectors: ps,
}
mc, err := d.st.StorePut(mi)
require.NoError(t, err)
// create the miner actor s.t. it exists in the init actors map
minerState, err := miner_spec.ConstructState(mc, periodBoundary, EmptyBitfieldCid, EmptyArrayCid, EmptyMapCid, EmptyDeadlinesCid)
require.NoError(t, err)
_, minerActorIDAddr, err := d.State().CreateActor(builtin_spec.StorageMinerActorCodeID, minerActorAddrs.RobustAddress, big_spec.Zero(), minerState)
require.NoError(t, err)
require.Equal(t, expectedMinerActorIDAddress, minerActorIDAddr)
// a miner actor has been created, exists in the state tree, and has an entry in the init actor.
// next update the storage power actor to track the miner
var spa power_spec.State
d.GetActorState(builtin_spec.StoragePowerActorAddr, &spa)
// set the miners claim
hm, err := adt_spec.AsMap(AsStore(d.State()), spa.Claims)
require.NoError(t, err)
// add claim for the miner
err = hm.Put(adt_spec.AddrKey(minerActorIDAddr), &power_spec.Claim{
RawBytePower: abi_spec.NewStoragePower(0),
QualityAdjPower: abi_spec.NewTokenAmount(0),
})
require.NoError(t, err)
// save the claim
spa.Claims, err = hm.Root()
require.NoError(t, err)
// update miner count
spa.MinerCount += 1
// update storage power actor's state in the tree
d.PutState(&spa)
return minerActorIDAddr
}
func AsStore(vmw *StateWrapper) adt_spec.Store {
return &storeWrapper{vmw: vmw}
}
type storeWrapper struct {
vmw *StateWrapper
}
func (s storeWrapper) Context() context.Context {
return context.TODO()
}
func (s storeWrapper) Get(ctx context.Context, c cid.Cid, out interface{}) error {
return s.vmw.StoreGet(c, out.(runtime.CBORUnmarshaler))
}
func (s storeWrapper) Put(ctx context.Context, v interface{}) (cid.Cid, error) {
return s.vmw.StorePut(v.(runtime.CBORMarshaler))
}

View File

@ -0,0 +1,198 @@
package drivers
import (
"context"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-datastore"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/types"
)
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 NewStateWrapper() *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) 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) (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) (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) (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, fmt.Errorf("register new address for actor: %w", err)
}
if err := tree.SetActor(addr, &actr.Actor); err != nil {
return nil, address.Undef, fmt.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
}

110
tvx/drivers/syscall.go Normal file
View File

@ -0,0 +1,110 @@
package drivers
import (
"bytes"
"github.com/filecoin-project/go-address"
commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid"
"github.com/minio/blake2b-simd"
)
var fakeVerifySignatureFunc = func(signature crypto.Signature, signer address.Address, plaintext []byte) error {
return nil
}
var defaultHashBlake2bFunc = func(data []byte) [32]byte {
return blake2b.Sum256(data)
}
var fakeComputerUnsealedSectorCIDFunc = func(proof abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error) {
// Fake CID computation by hashing the piece info (rather than the real computation over piece commitments).
buf := bytes.Buffer{}
for _, p := range pieces {
err := p.MarshalCBOR(&buf)
if err != nil {
panic(err)
}
}
token := blake2b.Sum256(buf.Bytes())
return commcid.DataCommitmentV1ToCID(token[:])
}
var fakeVerifySealFunc = func(info abi.SealVerifyInfo) error {
return nil
}
var fakeVerifyPoStFunc = func(info abi.WindowPoStVerifyInfo) error {
return nil
}
var fakeBatchVerifySealfunc = func(inp map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error) {
out := make(map[address.Address][]bool)
for a, svis := range inp {
res := make([]bool, len(svis))
for i := range res {
res[i] = true
}
out[a] = res
}
return out, nil
}
var panicingVerifyConsensusFaultFunc = func(h1, h2, extra []byte) (*runtime.ConsensusFault, error) {
panic("implement me")
}
type ChainValidationSysCalls struct {
VerifySigFunc func(signature crypto.Signature, signer address.Address, plaintext []byte) error
HashBlake2bFunc func(data []byte) [32]byte
ComputeUnSealedSectorCIDFunc func(proof abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error)
VerifySealFunc func(info abi.SealVerifyInfo) error
VerifyPoStFunc func(info abi.WindowPoStVerifyInfo) error
VerifyConsensusFaultFunc func(h1, h2, extra []byte) (*runtime.ConsensusFault, error)
BatchVerifySealsFunc func(map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error)
}
func NewChainValidationSysCalls() *ChainValidationSysCalls {
return &ChainValidationSysCalls{
HashBlake2bFunc: defaultHashBlake2bFunc,
VerifySigFunc: fakeVerifySignatureFunc,
ComputeUnSealedSectorCIDFunc: fakeComputerUnsealedSectorCIDFunc,
VerifySealFunc: fakeVerifySealFunc,
VerifyPoStFunc: fakeVerifyPoStFunc,
VerifyConsensusFaultFunc: panicingVerifyConsensusFaultFunc,
BatchVerifySealsFunc: fakeBatchVerifySealfunc,
}
}
func (c ChainValidationSysCalls) VerifySignature(signature crypto.Signature, signer address.Address, plaintext []byte) error {
return c.VerifySigFunc(signature, signer, plaintext)
}
func (c ChainValidationSysCalls) HashBlake2b(data []byte) [32]byte {
return c.HashBlake2bFunc(data)
}
func (c ChainValidationSysCalls) ComputeUnsealedSectorCID(proof abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error) {
return c.ComputeUnSealedSectorCIDFunc(proof, pieces)
}
func (c ChainValidationSysCalls) VerifySeal(info abi.SealVerifyInfo) error {
return c.VerifySealFunc(info)
}
func (c ChainValidationSysCalls) VerifyPoSt(info abi.WindowPoStVerifyInfo) error {
return c.VerifyPoStFunc(info)
}
func (c ChainValidationSysCalls) VerifyConsensusFault(h1, h2, extra []byte) (*runtime.ConsensusFault, error) {
return c.VerifyConsensusFaultFunc(h1, h2, extra)
}
func (c ChainValidationSysCalls) BatchVerifySeals(inp map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error) {
return c.BatchVerifySealsFunc(inp)
}

567
tvx/drivers/test_driver.go Normal file
View File

@ -0,0 +1,567 @@
package drivers
import (
"bytes"
"compress/gzip"
"context"
"encoding/binary"
"fmt"
"io"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/go-address"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
big_spec "github.com/filecoin-project/specs-actors/actors/abi/big"
builtin_spec "github.com/filecoin-project/specs-actors/actors/builtin"
account_spec "github.com/filecoin-project/specs-actors/actors/builtin/account"
cron_spec "github.com/filecoin-project/specs-actors/actors/builtin/cron"
init_spec "github.com/filecoin-project/specs-actors/actors/builtin/init"
market_spec "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
multisig_spec "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
power_spec "github.com/filecoin-project/specs-actors/actors/builtin/power"
reward_spec "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/builtin/system"
"github.com/filecoin-project/specs-actors/actors/runtime"
runtime_spec "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
adt_spec "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-blockservice"
cid "github.com/ipfs/go-cid"
datastore "github.com/ipfs/go-datastore"
blockstore "github.com/ipfs/go-ipfs-blockstore"
offline "github.com/ipfs/go-ipfs-exchange-offline"
cbor "github.com/ipfs/go-ipld-cbor"
format "github.com/ipfs/go-ipld-format"
"github.com/ipfs/go-merkledag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ipld/go-car"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/oni/tvx/chain"
vtypes "github.com/filecoin-project/oni/tvx/chain/types"
)
var (
// initialized by calling initializeStoreWithAdtRoots
EmptyArrayCid cid.Cid
EmptyDeadlinesCid cid.Cid
EmptyMapCid cid.Cid
EmptyMultiMapCid cid.Cid
EmptyBitfieldCid cid.Cid
)
var (
DefaultInitActorState ActorState
DefaultRewardActorState ActorState
DefaultBurntFundsActorState ActorState
DefaultStoragePowerActorState ActorState
DefaultStorageMarketActorState ActorState
DefaultSystemActorState ActorState
DefaultCronActorState ActorState
DefaultBuiltinActorsState []ActorState
)
const (
TestSealProofType = abi_spec.RegisteredSealProof_StackedDrg2KiBV1
)
func init() {
ms := newMockStore()
if err := initializeStoreWithAdtRoots(ms); err != nil {
panic(err)
}
DefaultInitActorState = ActorState{
Addr: builtin_spec.InitActorAddr,
Balance: big_spec.Zero(),
Code: builtin_spec.InitActorCodeID,
State: init_spec.ConstructState(EmptyMapCid, "chain-validation"),
}
firstRewardState := reward_spec.ConstructState(big_spec.Zero())
firstRewardState.ThisEpochReward = big_spec.NewInt(1e17)
DefaultRewardActorState = ActorState{
Addr: builtin_spec.RewardActorAddr,
Balance: TotalNetworkBalance,
Code: builtin_spec.RewardActorCodeID,
State: firstRewardState,
}
DefaultBurntFundsActorState = ActorState{
Addr: builtin_spec.BurntFundsActorAddr,
Balance: big_spec.Zero(),
Code: builtin_spec.AccountActorCodeID,
State: &account_spec.State{Address: builtin_spec.BurntFundsActorAddr},
}
DefaultStoragePowerActorState = ActorState{
Addr: builtin_spec.StoragePowerActorAddr,
Balance: big_spec.Zero(),
Code: builtin_spec.StoragePowerActorCodeID,
State: power_spec.ConstructState(EmptyMapCid, EmptyMultiMapCid),
}
DefaultStorageMarketActorState = ActorState{
Addr: builtin_spec.StorageMarketActorAddr,
Balance: big_spec.Zero(),
Code: builtin_spec.StorageMarketActorCodeID,
State: &market_spec.State{
Proposals: EmptyArrayCid,
States: EmptyArrayCid,
PendingProposals: EmptyMapCid,
EscrowTable: EmptyMapCid,
LockedTable: EmptyMapCid,
NextID: abi_spec.DealID(0),
DealOpsByEpoch: EmptyMultiMapCid,
LastCron: 0,
},
}
DefaultSystemActorState = ActorState{
Addr: builtin_spec.SystemActorAddr,
Balance: big_spec.Zero(),
Code: builtin_spec.SystemActorCodeID,
State: &system.State{},
}
DefaultCronActorState = ActorState{
Addr: builtin_spec.CronActorAddr,
Balance: big_spec.Zero(),
Code: builtin_spec.CronActorCodeID,
State: &cron_spec.State{Entries: []cron_spec.Entry{
{
Receiver: builtin_spec.StoragePowerActorAddr,
MethodNum: builtin_spec.MethodsPower.OnEpochTickEnd,
},
}},
}
DefaultBuiltinActorsState = []ActorState{
DefaultInitActorState,
DefaultRewardActorState,
DefaultBurntFundsActorState,
DefaultStoragePowerActorState,
DefaultStorageMarketActorState,
DefaultSystemActorState,
DefaultCronActorState,
}
}
func initializeStoreWithAdtRoots(store adt_spec.Store) error {
var err error
EmptyArrayCid, err = adt_spec.MakeEmptyArray(store).Root()
if err != nil {
return err
}
EmptyMapCid, err = adt_spec.MakeEmptyMap(store).Root()
if err != nil {
return err
}
EmptyMultiMapCid, err = adt_spec.MakeEmptyMultimap(store).Root()
if err != nil {
return err
}
EmptyDeadlinesCid, err = store.Put(context.TODO(), &miner.Deadline{
Partitions: EmptyArrayCid,
ExpirationsEpochs: EmptyArrayCid,
PostSubmissions: abi_spec.NewBitField(),
EarlyTerminations: abi_spec.NewBitField(),
LiveSectors: 0,
})
if err != nil {
return err
}
emptyBitfield := bitfield.NewFromSet(nil)
EmptyBitfieldCid, err = store.Put(context.TODO(), emptyBitfield)
if err != nil {
return err
}
return nil
}
type mockStore struct {
ctx context.Context
cbor.IpldStore
}
func newMockStore() *mockStore {
bs := blockstore.NewBlockstore(datastore.NewMapDatastore())
cst := cbor.NewCborStore(bs)
return &mockStore{
ctx: context.Background(),
IpldStore: cst,
}
}
func (m mockStore) Context() context.Context {
return m.ctx
}
func NewTestDriver() *TestDriver {
syscalls := NewChainValidationSysCalls()
stateWrapper := NewStateWrapper()
applier := NewApplier(stateWrapper, func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls {
return syscalls
})
sd := NewStateDriver(stateWrapper, newKeyManager())
err := initializeStoreWithAdtRoots(AsStore(sd.st))
require.NoError(t, err)
for _, acts := range DefaultBuiltinActorsState {
_, _, err := sd.State().CreateActor(acts.Code, acts.Addr, acts.Balance, acts.State)
require.NoError(t, err)
}
minerActorIDAddr := sd.newMinerAccountActor(TestSealProofType, abi_spec.ChainEpoch(0))
exeCtx := vtypes.NewExecutionContext(1, minerActorIDAddr)
producer := chain.NewMessageProducer(1000000000, big_spec.NewInt(1)) // gas limit ; gas price
checkExit := true
checkRet := true
config := NewConfig(checkExit, checkRet)
return &TestDriver{
StateDriver: sd,
MessageProducer: producer,
ExeCtx: exeCtx,
Config: config,
SysCalls: syscalls,
applier: applier,
}
}
type ActorState struct {
Addr address.Address
Balance abi_spec.TokenAmount
Code cid.Cid
State runtime_spec.CBORMarshaler
}
type TestDriver struct {
*StateDriver
applier *Applier
MessageProducer *chain.MessageProducer
TipSetMessageBuilder *TipSetMessageBuilder
ExeCtx *vtypes.ExecutionContext
Config *Config
SysCalls *ChainValidationSysCalls
}
//
// Unsigned Message Appliers
//
func (td *TestDriver) ApplyMessage(msg *types.Message) vtypes.ApplyMessageResult {
result := td.applyMessage(msg)
return result
}
func (td *TestDriver) ApplyOk(msg *types.Message) vtypes.ApplyMessageResult {
return td.ApplyExpect(msg, EmptyReturnValue)
}
func (td *TestDriver) ApplyExpect(msg *types.Message, retval []byte) vtypes.ApplyMessageResult {
return td.applyMessageExpectCodeAndReturn(msg, exitcode.Ok, retval)
}
func (td *TestDriver) ApplyFailure(msg *types.Message, code exitcode.ExitCode) vtypes.ApplyMessageResult {
return td.applyMessageExpectCodeAndReturn(msg, code, EmptyReturnValue)
}
func (td *TestDriver) applyMessageExpectCodeAndReturn(msg *types.Message, code exitcode.ExitCode, retval []byte) vtypes.ApplyMessageResult {
result := td.applyMessage(msg)
td.validateResult(result, code, retval)
return result
}
func (td *TestDriver) applyMessage(msg *types.Message) (result vtypes.ApplyMessageResult) {
defer func() {
if r := recover(); r != nil {
t.Fatalf("message application panicked: %v", r)
}
}()
result, err := td.applier.ApplyMessage(td.ExeCtx.Epoch, msg)
require.NoError(t, err)
return result
}
//
// Signed Message Appliers
//
func (td *TestDriver) ApplySigned(msg *types.Message) vtypes.ApplyMessageResult {
result := td.applyMessageSigned(msg)
return result
}
func (td *TestDriver) ApplySignedOk(msg *types.Message) vtypes.ApplyMessageResult {
return td.ApplySignedExpect(msg, EmptyReturnValue)
}
func (td *TestDriver) ApplySignedExpect(msg *types.Message, retval []byte) vtypes.ApplyMessageResult {
return td.applyMessageSignedExpectCodeAndReturn(msg, exitcode.Ok, retval)
}
func (td *TestDriver) ApplySignedFailure(msg *types.Message, code exitcode.ExitCode) vtypes.ApplyMessageResult {
return td.applyMessageExpectCodeAndReturn(msg, code, EmptyReturnValue)
}
func (td *TestDriver) applyMessageSignedExpectCodeAndReturn(msg *types.Message, code exitcode.ExitCode, retval []byte) vtypes.ApplyMessageResult {
result := td.applyMessageSigned(msg)
td.validateResult(result, code, retval)
return result
}
func (td *TestDriver) applyMessageSigned(msg *types.Message) (result vtypes.ApplyMessageResult) {
defer func() {
if r := recover(); r != nil {
t.Fatalf("message application panicked: %v", r)
}
}()
serMsg, err := msg.Serialize()
require.NoError(t, err)
msgSig, err := td.Wallet().Sign(msg.From, serMsg)
require.NoError(t, err)
smsgs := &types.SignedMessage{
Message: *msg,
Signature: msgSig,
}
result, err = td.applier.ApplySignedMessage(td.ExeCtx.Epoch, smsgs)
require.NoError(t, err)
return result
}
func (td *TestDriver) validateResult(result vtypes.ApplyMessageResult, code exitcode.ExitCode, retval []byte) {
if td.Config.ValidateExitCode() {
assert.Equal(t, code, result.Receipt.ExitCode, "Expected ExitCode: %s Actual ExitCode: %s", code.Error(), result.Receipt.ExitCode.Error())
}
if td.Config.ValidateReturnValue() {
assert.Equal(t, retval, result.Receipt.ReturnValue, "Expected ReturnValue: %v Actual ReturnValue: %v", retval, result.Receipt.ReturnValue)
}
}
func (td *TestDriver) AssertNoActor(addr address.Address) {
_, err := td.State().Actor(addr)
assert.Error(t, err, "expected no such actor %s", addr)
}
func (td *TestDriver) GetBalance(addr address.Address) abi_spec.TokenAmount {
actr, err := td.State().Actor(addr)
require.NoError(t, err)
return actr.Balance()
}
func (td *TestDriver) GetHead(addr address.Address) cid.Cid {
actr, err := td.State().Actor(addr)
require.NoError(t, err)
return actr.Head()
}
// AssertBalance checks an actor has an expected balance.
func (td *TestDriver) AssertBalance(addr address.Address, expected abi_spec.TokenAmount) {
actr, err := td.State().Actor(addr)
require.NoError(t, err)
assert.Equal(t, expected, actr.Balance(), fmt.Sprintf("expected actor %s balance: %s, actual balance: %s", addr, expected, actr.Balance()))
}
// Checks an actor's balance and callSeqNum.
func (td *TestDriver) AssertActor(addr address.Address, balance abi_spec.TokenAmount, callSeqNum uint64) {
actr, err := td.State().Actor(addr)
require.NoError(t, err)
assert.Equal(t, balance, actr.Balance(), fmt.Sprintf("expected actor %s balance: %s, actual balance: %s", addr, balance, actr.Balance()))
assert.Equal(t, callSeqNum, actr.CallSeqNum(), fmt.Sprintf("expected actor %s callSeqNum: %d, actual : %d", addr, callSeqNum, actr.CallSeqNum()))
}
func (td *TestDriver) AssertHead(addr address.Address, expected cid.Cid) {
head := td.GetHead(addr)
assert.Equal(t, expected, head, "expected actor %s head %s, actual %s", addr, expected, head)
}
func (td *TestDriver) AssertBalanceCallback(addr address.Address, thing func(actorBalance abi_spec.TokenAmount) bool) {
actr, err := td.State().Actor(addr)
require.NoError(t, err)
assert.True(t, thing(actr.Balance()))
}
func (td *TestDriver) AssertMultisigTransaction(multisigAddr address.Address, txnID multisig_spec.TxnID, txn multisig_spec.Transaction) {
var msState multisig_spec.State
td.GetActorState(multisigAddr, &msState)
txnMap, err := adt_spec.AsMap(AsStore(td.State()), msState.PendingTxns)
require.NoError(t, err)
var actualTxn multisig_spec.Transaction
found, err := txnMap.Get(txnID, &actualTxn)
require.NoError(t, err)
require.True(t, found)
assert.Equal(t, txn, actualTxn)
}
func (td *TestDriver) AssertMultisigContainsTransaction(multisigAddr address.Address, txnID multisig_spec.TxnID, contains bool) {
var msState multisig_spec.State
td.GetActorState(multisigAddr, &msState)
txnMap, err := adt_spec.AsMap(AsStore(td.State()), msState.PendingTxns)
require.NoError(t, err)
var actualTxn multisig_spec.Transaction
found, err := txnMap.Get(txnID, &actualTxn)
require.NoError(t, err)
assert.Equal(t, contains, found)
}
func (td *TestDriver) AssertMultisigState(multisigAddr address.Address, expected multisig_spec.State) {
var msState multisig_spec.State
td.GetActorState(multisigAddr, &msState)
assert.NotNil(t, msState)
assert.Equal(t, expected.InitialBalance, msState.InitialBalance, fmt.Sprintf("expected InitialBalance: %v, actual InitialBalance: %v", expected.InitialBalance, msState.InitialBalance))
assert.Equal(t, expected.NextTxnID, msState.NextTxnID, fmt.Sprintf("expected NextTxnID: %v, actual NextTxnID: %v", expected.NextTxnID, msState.NextTxnID))
assert.Equal(t, expected.NumApprovalsThreshold, msState.NumApprovalsThreshold, fmt.Sprintf("expected NumApprovalsThreshold: %v, actual NumApprovalsThreshold: %v", expected.NumApprovalsThreshold, msState.NumApprovalsThreshold))
assert.Equal(t, expected.StartEpoch, msState.StartEpoch, fmt.Sprintf("expected StartEpoch: %v, actual StartEpoch: %v", expected.StartEpoch, msState.StartEpoch))
assert.Equal(t, expected.UnlockDuration, msState.UnlockDuration, fmt.Sprintf("expected UnlockDuration: %v, actual UnlockDuration: %v", expected.UnlockDuration, msState.UnlockDuration))
for _, e := range expected.Signers {
assert.Contains(t, msState.Signers, e, fmt.Sprintf("expected Signer: %v, actual Signer: %v", e, msState.Signers))
}
}
func (td *TestDriver) ComputeInitActorExecReturn(from address.Address, originatorCallSeq uint64, newActorAddressCount uint64, expectedNewAddr address.Address) init_spec.ExecReturn {
return computeInitActorExecReturn(from, originatorCallSeq, newActorAddressCount, expectedNewAddr)
}
func computeInitActorExecReturn(from address.Address, originatorCallSeq uint64, newActorAddressCount uint64, expectedNewAddr address.Address) init_spec.ExecReturn {
buf := new(bytes.Buffer)
if from.Protocol() == address.ID {
t.Fatal("cannot compute init actor address return from ID address", from)
}
require.NoError(t, from.MarshalCBOR(buf))
require.NoError(t, binary.Write(buf, binary.BigEndian, originatorCallSeq))
require.NoError(t, binary.Write(buf, binary.BigEndian, newActorAddressCount))
out, err := address.NewActorAddress(buf.Bytes())
require.NoError(t, err)
return init_spec.ExecReturn{
IDAddress: expectedNewAddr,
RobustAddress: out,
}
}
func (td *TestDriver) MustCreateAndVerifyMultisigActor(nonce uint64, value abi_spec.TokenAmount, multisigAddr address.Address, from address.Address, params *multisig_spec.ConstructorParams, code exitcode.ExitCode, retval []byte) {
/* Create the Multisig actor*/
td.applyMessageExpectCodeAndReturn(
td.MessageProducer.CreateMultisigActor(from, params.Signers, params.UnlockDuration, params.NumApprovalsThreshold, chain.Nonce(nonce), chain.Value(value)),
code, retval)
/* Assert the actor state was setup as expected */
pendingTxMapRoot, err := adt_spec.MakeEmptyMap(newMockStore()).Root()
require.NoError(t, err)
initialBalance := big_spec.Zero()
startEpoch := abi_spec.ChainEpoch(0)
if params.UnlockDuration > 0 {
initialBalance = value
startEpoch = td.ExeCtx.Epoch
}
td.AssertMultisigState(multisigAddr, multisig_spec.State{
NextTxnID: 0,
InitialBalance: initialBalance,
StartEpoch: startEpoch,
Signers: params.Signers,
UnlockDuration: params.UnlockDuration,
NumApprovalsThreshold: params.NumApprovalsThreshold,
PendingTxns: pendingTxMapRoot,
})
td.AssertBalance(multisigAddr, value)
}
type RewardSummary struct {
Treasury abi_spec.TokenAmount
SimpleSupply abi_spec.TokenAmount
BaselineSupply abi_spec.TokenAmount
NextPerEpochReward abi_spec.TokenAmount
NextPerBlockReward abi_spec.TokenAmount
}
func (td *TestDriver) GetRewardSummary() *RewardSummary {
var rst reward_spec.State
td.GetActorState(builtin_spec.RewardActorAddr, &rst)
return &RewardSummary{
Treasury: td.GetBalance(builtin_spec.RewardActorAddr),
NextPerEpochReward: rst.ThisEpochReward,
NextPerBlockReward: big_spec.Div(rst.ThisEpochReward, big_spec.NewInt(builtin_spec.ExpectedLeadersPerEpoch)),
}
}
func (td *TestDriver) GetStateRoot() cid.Cid {
return td.st.stateRoot
}
func (td *TestDriver) MustMarshalGzippedCAR(roots ...cid.Cid) []byte {
var b bytes.Buffer
gw := gzip.NewWriter(&b)
err := td.MarshalCAR(gw, roots...)
if err != nil {
panic(err)
}
gw.Close()
return b.Bytes()
}
func (td *TestDriver) MarshalCAR(w io.Writer, roots ...cid.Cid) error {
ctx := context.Background()
offl := offline.Exchange(td.st.bs)
blkserv := blockservice.New(td.st.bs, offl)
dserv := merkledag.NewDAGService(blkserv)
var cids []cid.Cid
cids = append(cids, roots...)
if err := car.WriteCarWithWalker(ctx, dserv, cids, w, walker); err != nil {
return fmt.Errorf("failed to write car file: %w", err)
}
return nil
}
func walker(nd format.Node) (out []*format.Link, err error) {
for _, link := range nd.Links() {
if link.Cid.Prefix().Codec == cid.FilCommitmentSealed || link.Cid.Prefix().Codec == cid.FilCommitmentUnsealed {
continue
}
out = append(out, link)
}
return out, nil
}

View File

@ -0,0 +1,201 @@
package drivers
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
vtypes "github.com/filecoin-project/oni/tvx/chain/types"
)
type TipSetMessageBuilder struct {
driver *TestDriver
bbs []*BlockBuilder
}
func NewTipSetMessageBuilder(testDriver *TestDriver) *TipSetMessageBuilder {
return &TipSetMessageBuilder{
driver: testDriver,
bbs: nil,
}
}
func (t *TipSetMessageBuilder) WithBlockBuilder(bb *BlockBuilder) *TipSetMessageBuilder {
t.bbs = append(t.bbs, bb)
return t
}
func (t *TipSetMessageBuilder) Apply() vtypes.ApplyTipSetResult {
result := t.apply()
t.Clear()
return result
}
func (t *TipSetMessageBuilder) ApplyAndValidate() vtypes.ApplyTipSetResult {
result := t.apply()
t.validateResult(result)
t.Clear()
return result
}
func (tb *TipSetMessageBuilder) apply() vtypes.ApplyTipSetResult {
var blks []vtypes.BlockMessagesInfo
for _, b := range tb.bbs {
blks = append(blks, b.build())
}
result, err := tb.driver.applier.ApplyTipSetMessages(tb.driver.ExeCtx.Epoch, blks, tb.driver.Randomness())
require.NoError(t, err)
//t.driver.StateTracker.TrackResult(result)
return result
}
func (tb *TipSetMessageBuilder) validateResult(result vtypes.ApplyTipSetResult) {
expected := []ExpectedResult{}
for _, b := range tb.bbs {
expected = append(expected, b.expectedResults...)
}
if len(result.Receipts) > len(expected) {
t.Fatalf("ApplyTipSetMessages returned more result than expected. Expected: %d, Actual: %d", len(expected), len(result.Receipts))
return
}
for i := range result.Receipts {
if tb.driver.Config.ValidateExitCode() {
assert.Equal(t, expected[i].ExitCode, result.Receipts[i].ExitCode, "Message Number: %d Expected ExitCode: %s Actual ExitCode: %s", i, expected[i].ExitCode.Error(), result.Receipts[i].ExitCode.Error())
}
if tb.driver.Config.ValidateReturnValue() {
assert.Equal(t, expected[i].ReturnVal, result.Receipts[i].ReturnValue, "Message Number: %d Expected ReturnValue: %v Actual ReturnValue: %v", i, expected[i].ReturnVal, result.Receipts[i].ReturnValue)
}
}
}
func (t *TipSetMessageBuilder) Clear() {
t.bbs = nil
}
type BlockBuilder struct {
TD *TestDriver
miner address.Address
ticketCount int64
secpMsgs []*types.SignedMessage
blsMsgs []*types.Message
expectedResults []ExpectedResult
}
type ExpectedResult struct {
ExitCode exitcode.ExitCode
ReturnVal []byte
}
func NewBlockBuilder(td *TestDriver, miner address.Address) *BlockBuilder {
return &BlockBuilder{
TD: td,
miner: miner,
ticketCount: 1,
secpMsgs: nil,
blsMsgs: nil,
expectedResults: nil,
}
}
func (bb *BlockBuilder) addResult(code exitcode.ExitCode, retval []byte) {
bb.expectedResults = append(bb.expectedResults, ExpectedResult{
ExitCode: code,
ReturnVal: retval,
})
}
func (bb *BlockBuilder) WithBLSMessageOk(blsMsg *types.Message) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, blsMsg)
bb.addResult(exitcode.Ok, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithBLSMessageDropped(blsMsg *types.Message) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, blsMsg)
return bb
}
func (bb *BlockBuilder) WithBLSMessageAndCode(bm *types.Message, code exitcode.ExitCode) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, bm)
bb.addResult(code, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithBLSMessageAndRet(bm *types.Message, retval []byte) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, bm)
bb.addResult(exitcode.Ok, retval)
return bb
}
func (bb *BlockBuilder) WithSECPMessageAndCode(bm *types.Message, code exitcode.ExitCode) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
bb.addResult(code, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithSECPMessageAndRet(bm *types.Message, retval []byte) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
bb.addResult(exitcode.Ok, retval)
return bb
}
func (bb *BlockBuilder) WithSECPMessageOk(bm *types.Message) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
bb.addResult(exitcode.Ok, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithSECPMessageDropped(bm *types.Message) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
return bb
}
func (bb *BlockBuilder) WithTicketCount(count int64) *BlockBuilder {
bb.ticketCount = count
return bb
}
func (bb *BlockBuilder) toSignedMessage(m *types.Message) *types.SignedMessage {
from := m.From
if from.Protocol() == address.ID {
from = bb.TD.ActorPubKey(from)
}
if from.Protocol() != address.SECP256K1 {
t.Fatalf("Invalid address for SECP signature, address protocol: %v", from.Protocol())
}
raw, err := m.Serialize()
require.NoError(t, err)
sig, err := bb.TD.Wallet().Sign(from, raw)
require.NoError(t, err)
return &types.SignedMessage{
Message: *m,
Signature: sig,
}
}
func (bb *BlockBuilder) build() vtypes.BlockMessagesInfo {
return vtypes.BlockMessagesInfo{
BLSMessages: bb.blsMsgs,
SECPMessages: bb.secpMsgs,
Miner: bb.miner,
TicketCount: bb.ticketCount,
}
}

39
tvx/drivers/various.go Normal file
View File

@ -0,0 +1,39 @@
package drivers
import (
"context"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/ipfs/go-cid"
big_spec "github.com/filecoin-project/specs-actors/actors/abi/big"
)
const (
totalFilecoin = 2_000_000_000
filecoinPrecision = 1_000_000_000_000_000_000
)
var (
TotalNetworkBalance = big_spec.Mul(big_spec.NewInt(totalFilecoin), big_spec.NewInt(filecoinPrecision))
EmptyReturnValue = []byte{}
)
// Actor is an abstraction over the actor states stored in the root of the state tree.
type Actor interface {
Code() cid.Cid
Head() cid.Cid
CallSeqNum() uint64
Balance() big.Int
}
type contextStore struct {
cbor.IpldStore
ctx context.Context
}
func (s *contextStore) Context() context.Context {
return s.ctx
}

View File

@ -4,26 +4,38 @@ go 1.14
require (
github.com/davecgh/go-spew v1.1.1
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d
github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef
github.com/filecoin-project/lotus v0.4.3-0.20200801235920-43491cb7edfd
github.com/filecoin-project/sector-storage v0.0.0-20200730203805-7153e1dd05b5
github.com/filecoin-project/go-bitfield v0.1.2
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
github.com/filecoin-project/lotus v0.4.3-0.20200803225238-cd8537e76fc0
github.com/filecoin-project/sector-storage v0.0.0-20200803184904-3cab915fd225
github.com/filecoin-project/specs-actors v0.8.6
github.com/hashicorp/go-multierror v1.1.0
github.com/ipfs/go-block-format v0.0.2
github.com/ipfs/go-blockservice v0.1.4-0.20200624145336-a978cec6e834
github.com/ipfs/go-cid v0.0.7
github.com/ipfs/go-datastore v0.4.4
github.com/ipfs/go-hamt-ipld v0.1.1
github.com/ipfs/go-ipfs-blockstore v1.0.0
github.com/ipfs/go-ipfs-exchange-interface v0.0.1
github.com/ipfs/go-ipfs-exchange-offline v0.0.1
github.com/ipfs/go-ipld-cbor v0.0.5-0.20200428170625-a0bd04d3cbdf
github.com/ipfs/go-ipld-format v0.2.0
github.com/ipfs/go-merkledag v0.3.1
github.com/ipld/go-car v0.1.1-0.20200526133713-1c7508d55aae
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52
github.com/libp2p/go-libp2p-core v0.6.1
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
github.com/multiformats/go-multiaddr v0.2.2
github.com/multiformats/go-multiaddr-net v0.1.5
github.com/multiformats/go-multihash v0.0.14
github.com/multiformats/go-varint v0.0.6
github.com/stretchr/testify v1.6.1
github.com/urfave/cli/v2 v2.2.0
github.com/whyrusleeping/cbor-gen v0.0.0-20200723185710-6a3894a6352b
)
replace github.com/filecoin-project/filecoin-ffi => ../extra/filecoin-ffi
replace github.com/supranational/blst => github.com/supranational/blst v0.1.2-alpha.1

View File

@ -204,7 +204,6 @@ github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef h1:W
github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef/go.mod h1:SrA+pWVoUivqKOfC+ckVYbx41hWz++HxJcrlmHNnebU=
github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200131012142-05d80eeccc5e/go.mod h1:boRtQhzmxNocrMxOXo1NYn4oUc1NGvR8tEa79wApNXg=
github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200424220931-6263827e49f2/go.mod h1:boRtQhzmxNocrMxOXo1NYn4oUc1NGvR8tEa79wApNXg=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UNxPeOYaXhBWSNsVaM=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20200731171407-e559a0579161 h1:K6t4Hrs+rwUxBz2xg88Bdqeh4k5/rycQFdPseZhRyfE=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20200731171407-e559a0579161/go.mod h1:vgmwKBkx+ca5OIeEvstiQgzAZnb7R6QaqE1oEDSqa6g=
@ -237,7 +236,6 @@ github.com/filecoin-project/go-paramfetch v0.0.2-0.20200218225740-47c639bab663/g
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 h1:A256QonvzRaknIIAuWhe/M2dpV2otzs3NBhi5TWa/UA=
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261/go.mod h1:fZzmf4tftbwf9S37XRifoJlz7nCjRdIrMGLR07dKLCc=
github.com/filecoin-project/go-statemachine v0.0.0-20200226041606-2074af6d51d9/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989 h1:1GjCS3xy/CRIw7Tq0HfzX6Al8mklrszQZ3iIFnjPzHk=
github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v0.0.0-20200730031800-c3336614d2a7 h1:KAF3WM/xSnl6G6RHX8vDJthg4+e4PSgBh72//6c6Qvc=
github.com/filecoin-project/go-statemachine v0.0.0-20200730031800-c3336614d2a7/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
@ -245,12 +243,12 @@ github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIi
github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI=
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg=
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8=
github.com/filecoin-project/lotus v0.4.3-0.20200801235920-43491cb7edfd h1:8C71dmpHfOdq/MizvVwSuZhCGo3rL23T+qlUykAffF4=
github.com/filecoin-project/lotus v0.4.3-0.20200801235920-43491cb7edfd/go.mod h1:c0UiPstI62Kcmv/A5tb2akEngFGDKw5RAqOjT30PjxQ=
github.com/filecoin-project/lotus v0.4.3-0.20200803225238-cd8537e76fc0 h1:A1IUDzAu/+BtSG7yqcv9hAM7bShsxOi6PB38970FfGM=
github.com/filecoin-project/lotus v0.4.3-0.20200803225238-cd8537e76fc0/go.mod h1:byIqtCuSkVu9LZm8dShhO/FojO9EbAV8DLG7jxGrnR0=
github.com/filecoin-project/sector-storage v0.0.0-20200712023225-1d67dcfa3c15/go.mod h1:salgVdX7qeXFo/xaiEQE29J4pPkjn71T0kt0n+VDBzo=
github.com/filecoin-project/sector-storage v0.0.0-20200730050024-3ee28c3b6d9a/go.mod h1:oOawOl9Yk+qeytLzzIryjI8iRbqo+qzS6EEeElP4PWA=
github.com/filecoin-project/sector-storage v0.0.0-20200730203805-7153e1dd05b5 h1:jULKRxvzn6CIKcKi74mGH0w1i54KXgD29IP7EhXBavQ=
github.com/filecoin-project/sector-storage v0.0.0-20200730203805-7153e1dd05b5/go.mod h1:oOawOl9Yk+qeytLzzIryjI8iRbqo+qzS6EEeElP4PWA=
github.com/filecoin-project/sector-storage v0.0.0-20200803184904-3cab915fd225 h1:Or2lM5Cdsq0nDrSWp2YO70tjd8Ohg0jVWT/KGP3BX+I=
github.com/filecoin-project/sector-storage v0.0.0-20200803184904-3cab915fd225/go.mod h1:oOawOl9Yk+qeytLzzIryjI8iRbqo+qzS6EEeElP4PWA=
github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA=
github.com/filecoin-project/specs-actors v0.3.0/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y=
github.com/filecoin-project/specs-actors v0.6.1/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY=
@ -264,7 +262,6 @@ github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea/g
github.com/filecoin-project/storage-fsm v0.0.0-20200730122205-d423ae90d8d4/go.mod h1:1CGbd11KkHuyWPT+xwwCol1zl/jnlpiKD2L4fzKxaiI=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
@ -314,7 +311,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
@ -343,7 +339,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/google/gopacket v1.1.18 h1:lum7VRA9kdlvBi7/v2p7/zcbkduHaCH/SVVyurs7OpY=
github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
@ -458,7 +453,6 @@ github.com/ipfs/go-cid v0.0.4-0.20191112011718-79e75dffeb10/go.mod h1:/BYOuUoxkE
github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
github.com/ipfs/go-cid v0.0.6-0.20200501230655-7c82f3b81c00/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
github.com/ipfs/go-cid v0.0.6 h1:go0y+GcDOGeJIV01FeBsta4FHngoA4Wz7KMeLkXAhMs=
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY=
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
@ -699,7 +693,6 @@ github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniV
github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o=
github.com/libp2p/go-libp2p v0.8.3/go.mod h1:EsH1A+8yoWK+L4iKcbPYu6MPluZ+CHWI9El8cTaefiM=
github.com/libp2p/go-libp2p v0.9.2/go.mod h1:cunHNLDVus66Ct9iXXcjKRLdmHdFdHVe1TAnbubJQqQ=
github.com/libp2p/go-libp2p v0.10.0 h1:7ooOvK1wi8eLpyTppy8TeH43UHy5uI75GAHGJxenUi0=
github.com/libp2p/go-libp2p v0.10.0/go.mod h1:yBJNpb+mGJdgrwbKAKrhPU0u3ogyNFTfjJ6bdM+Q/G8=
github.com/libp2p/go-libp2p v0.10.2 h1:VQOo/Pbj9Ijco9jiMYN5ImAg236IjTXfnUPJ2OvbpLM=
github.com/libp2p/go-libp2p v0.10.2/go.mod h1:BYckt6lmS/oA1SlRETSPWSUulCQKiZuTVsymVMc//HQ=
@ -710,7 +703,6 @@ github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/
github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI=
github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI=
github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A=
github.com/libp2p/go-libp2p-autonat v0.2.3 h1:w46bKK3KTOUWDe5mDYMRjJu1uryqBp8HCNDp/TWMqKw=
github.com/libp2p/go-libp2p-autonat v0.2.3/go.mod h1:2U6bNWCNsAG9LEbwccBDQbjzQ8Krdjge1jLTE9rdoMM=
github.com/libp2p/go-libp2p-autonat v0.3.1 h1:60sc3NuQz+RxEb4ZVCRp/7uPtD7gnlLcOIKYNulzSIo=
github.com/libp2p/go-libp2p-autonat v0.3.1/go.mod h1:0OzOi1/cVc7UcxfOddemYD5vzEqi4fwRbnZcJGLi68U=
@ -719,7 +711,6 @@ github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg=
github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU=
github.com/libp2p/go-libp2p-blankhost v0.1.6 h1:CkPp1/zaCrCnBo0AdsQA0O1VkUYoUOtyHOnoa8gKIcE=
github.com/libp2p/go-libp2p-blankhost v0.1.6/go.mod h1:jONCAJqEP+Z8T6EQviGL4JsQcLx1LgTGtVqFNY8EMfQ=
github.com/libp2p/go-libp2p-blankhost v0.2.0 h1:3EsGAi0CBGcZ33GwRuXEYJLLPoVWyXJ1bcJzAJjINkk=
github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ=
@ -731,7 +722,6 @@ github.com/libp2p/go-libp2p-circuit v0.1.3/go.mod h1:Xqh2TjSy8DD5iV2cCOMzdynd6h8
github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU=
github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo=
github.com/libp2p/go-libp2p-circuit v0.2.2/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCyJp1Eo4A1xYdpjfs4=
github.com/libp2p/go-libp2p-circuit v0.2.3 h1:3Uw1fPHWrp1tgIhBz0vSOxRUmnKL8L/NGUyEd5WfSGM=
github.com/libp2p/go-libp2p-circuit v0.2.3/go.mod h1:nkG3iE01tR3FoQ2nMm06IUrCpCyJp1Eo4A1xYdpjfs4=
github.com/libp2p/go-libp2p-circuit v0.3.1 h1:69ENDoGnNN45BNDnBd+8SXSetDuw0eJFcGmOvvtOgBw=
github.com/libp2p/go-libp2p-circuit v0.3.1/go.mod h1:8RMIlivu1+RxhebipJwFDA45DasLx+kkrp4IlJj53F4=
@ -760,7 +750,6 @@ github.com/libp2p/go-libp2p-core v0.5.4/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt
github.com/libp2p/go-libp2p-core v0.5.5/go.mod h1:vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM=
github.com/libp2p/go-libp2p-core v0.5.6/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo=
github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo=
github.com/libp2p/go-libp2p-core v0.6.0 h1:u03qofNYTBN+yVg08PuAKylZogVf0xcTEeM8skGf+ak=
github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo=
github.com/libp2p/go-libp2p-core v0.6.1 h1:XS+Goh+QegCDojUZp00CaPMfiEADCrLjNZskWE7pvqs=
github.com/libp2p/go-libp2p-core v0.6.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8=
@ -773,7 +762,6 @@ github.com/libp2p/go-libp2p-discovery v0.0.5/go.mod h1:YtF20GUxjgoKZ4zmXj8j3Nb2T
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg=
github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw=
github.com/libp2p/go-libp2p-discovery v0.4.0 h1:dK78UhopBk48mlHtRCzbdLm3q/81g77FahEBTjcqQT8=
github.com/libp2p/go-libp2p-discovery v0.4.0/go.mod h1:bZ0aJSrFc/eX2llP0ryhb1kpgkPyTo23SJ5b7UQCMh4=
github.com/libp2p/go-libp2p-discovery v0.5.0 h1:Qfl+e5+lfDgwdrXdu4YNCWyEo3fWuP+WgN9mN0iWviQ=
github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug=
@ -795,7 +783,6 @@ github.com/libp2p/go-libp2p-mplex v0.1.1/go.mod h1:KUQWpGkCzfV7UIpi8SKsAVxyBgz1c
github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo=
github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE=
github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo=
github.com/libp2p/go-libp2p-mplex v0.2.3 h1:2zijwaJvpdesST2MXpI5w9wWFRgYtMcpRX7rrw0jmOo=
github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek=
github.com/libp2p/go-libp2p-mplex v0.2.4 h1:XFFXaN4jhqnIuJVjYOR3k6bnRj0mFfJOlIuDVww+4Zo=
github.com/libp2p/go-libp2p-mplex v0.2.4/go.mod h1:mI7iOezdWFOisvUwaYd3IDrJ4oVmgoXK8H331ui39CE=
@ -834,13 +821,11 @@ github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h
github.com/libp2p/go-libp2p-pubsub v0.3.4-0.20200731161531-2b5243c72f0d h1:1kfMc74C1DZGh97VJpA5efPXWU3tmdRF/wKYbFYya/4=
github.com/libp2p/go-libp2p-pubsub v0.3.4-0.20200731161531-2b5243c72f0d/go.mod h1:DTMSVmZZfXodB/pvdTGrY2eHPZ9W2ev7hzTH83OKHrI=
github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU=
github.com/libp2p/go-libp2p-quic-transport v0.5.0 h1:BUN1lgYNUrtv4WLLQ5rQmC9MCJ6uEXusezGvYRNoJXE=
github.com/libp2p/go-libp2p-quic-transport v0.5.0/go.mod h1:IEcuC5MLxvZ5KuHKjRu+dr3LjCT1Be3rcD/4d8JrX8M=
github.com/libp2p/go-libp2p-quic-transport v0.7.1/go.mod h1:TD31to4E5exogR/GWHClXCfkktigjAl5rXSt7HoxNvY=
github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q=
github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q=
github.com/libp2p/go-libp2p-record v0.1.1/go.mod h1:VRgKajOyMVgP/F0L5g3kH7SVskp17vFi2xheb5uMJtg=
github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0=
github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk=
github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs28kCIfql0=
github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4=
@ -861,7 +846,6 @@ github.com/libp2p/go-libp2p-swarm v0.2.1/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+
github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU=
github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM=
github.com/libp2p/go-libp2p-swarm v0.2.4/go.mod h1:/xIpHFPPh3wmSthtxdGbkHZ0OET1h/GGZes8Wku/M5Y=
github.com/libp2p/go-libp2p-swarm v0.2.7 h1:4lV/sf7f0NuVqunOpt1I11+Z54+xp+m0eeAvxj/LyRc=
github.com/libp2p/go-libp2p-swarm v0.2.7/go.mod h1:ZSJ0Q+oq/B1JgfPHJAT2HTall+xYRNYp1xs4S2FBWKA=
github.com/libp2p/go-libp2p-swarm v0.2.8 h1:cIUUvytBzNQmGSjnXFlI6UpoBGsaud82mJPIJVfkDlg=
github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM=
@ -870,7 +854,6 @@ github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MB
github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
github.com/libp2p/go-libp2p-testing v0.1.1 h1:U03z3HnGI7Ni8Xx6ONVZvUFOAzWYmolWf5W5jAOPNmU=
github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8 h1:v4dvk7YEW8buwCdIVWnhpv0Hp/AAJKRWIxBhmLRZrsk=
github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc=
@ -908,7 +891,6 @@ github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3
github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA=
github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-msgio v0.0.6 h1:lQ7Uc0kS1wb1EfRxO2Eir/RJoHkHn7t6o+EiwsYIKJA=
github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA=
@ -916,14 +898,12 @@ github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36Gchpc
github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo=
github.com/libp2p/go-nat v0.0.5 h1:qxnwkco8RLKqVh1NmjQ+tJ8p8khNLFxuElYG/TwqW4Q=
github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU=
github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR4Xg=
github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk=
github.com/libp2p/go-netroute v0.1.3 h1:1ngWRx61us/EpaKkdqkMjKk/ufr/JlIFYQAxV2XX8Ig=
github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk=
github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0=
github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-openssl v0.0.5 h1:pQkejVhF0xp08D4CQUcw8t+BFJeXowja6RVcb5p++EA=
github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw=
github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
@ -970,7 +950,6 @@ github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/h
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
github.com/lucas-clemente/quic-go v0.16.0 h1:jJw36wfzGJhmOhAOaOC2lS36WgeqXQszH47A7spo1LI=
github.com/lucas-clemente/quic-go v0.16.0/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
github.com/lucas-clemente/quic-go v0.17.3/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg=
@ -981,7 +960,6 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
github.com/marten-seemann/qtls v0.9.1 h1:O0YKQxNVPaiFgMng0suWEOY2Sb4LT2sRn9Qimq3Z1IQ=
github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
@ -1037,7 +1015,6 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
@ -1087,13 +1064,11 @@ github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUj
github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
github.com/multiformats/go-multistream v0.1.1 h1:JlAdpIFhBhGRLxe9W6Om0w++Gd6KMWoFPZL/dEnm9nI=
github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38=
github.com/multiformats/go-multistream v0.1.2 h1:knyamLYMPFPngQjGQ0lhnlys3jtVR/3xV6TREUJr+fE=
github.com/multiformats/go-multistream v0.1.2/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg=
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
@ -1135,7 +1110,6 @@ github.com/opentracing-contrib/go-stdlib v0.0.0-20190519235532-cf7a6c988dc9/go.m
github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
@ -1292,8 +1266,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/supranational/blst v0.1.1 h1:GsK4oq7QZ7yfHI6dCh2NQsUe4imjlFwm5NXF5PWAWoo=
github.com/supranational/blst v0.1.1/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/supranational/blst v0.1.2-alpha.1 h1:v0UqVlvbRNZIaSeMPr+T01kvTUq1h0EZuZ6gnDR1Mlg=
github.com/supranational/blst v0.1.2-alpha.1/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
@ -1380,7 +1354,6 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@ -1531,7 +1504,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@ -33,6 +33,7 @@ func main() {
extractMsgCmd,
execLotusCmd,
examineCmd,
suiteMessagesCmd,
},
}

View File

@ -0,0 +1,216 @@
package main
import (
"encoding/json"
"os"
"github.com/hashicorp/go-multierror"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-address"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
big_spec "github.com/filecoin-project/specs-actors/actors/abi/big"
exitcode_spec "github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/filecoin-project/oni/tvx/chain"
"github.com/filecoin-project/oni/tvx/drivers"
)
var suiteMessagesCmd = &cli.Command{
Name: "suite-messages",
Description: "",
Action: suiteMessages,
}
func suiteMessages(c *cli.Context) error {
var err *multierror.Error
err = multierror.Append(MessageTest_AccountActorCreation())
err = multierror.Append(MessageTest_InitActorSequentialIDAddressCreate())
err = multierror.Append(MessageTest_MessageApplicationEdgecases())
return err.ErrorOrNil()
}
func MessageTest_AccountActorCreation() error {
testCases := []struct {
desc string
existingActorType address.Protocol
existingActorBal abi_spec.TokenAmount
newActorAddr address.Address
newActorInitBal abi_spec.TokenAmount
expExitCode exitcode_spec.ExitCode
}{
{
"success create SECP256K1 account actor",
address.SECP256K1,
abi_spec.NewTokenAmount(10_000_000_000),
chain.MustNewSECP256K1Addr("publickeyfoo"),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.Ok,
},
{
"success create BLS account actor",
address.SECP256K1,
abi_spec.NewTokenAmount(10_000_000_000),
chain.MustNewBLSAddr(1),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.Ok,
},
{
"fail create SECP256K1 account actor insufficient balance",
address.SECP256K1,
abi_spec.NewTokenAmount(9_999),
chain.MustNewSECP256K1Addr("publickeybar"),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.SysErrSenderStateInvalid,
},
{
"fail create BLS account actor insufficient balance",
address.SECP256K1,
abi_spec.NewTokenAmount(9_999),
chain.MustNewBLSAddr(1),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.SysErrSenderStateInvalid,
},
// TODO add edge case tests that have insufficient balance after gas fees
}
for _, tc := range testCases {
err := func() error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
existingAccountAddr, _ := td.NewAccountActor(tc.existingActorType, tc.existingActorBal)
preroot := td.GetStateRoot()
msg := td.MessageProducer.Transfer(existingAccountAddr, tc.newActorAddr, chain.Value(tc.newActorInitBal), chain.Nonce(0))
b, err := msg.Serialize()
if err != nil {
return err
}
v.ApplyMessages = []HexEncodedBytes{b}
result := td.ApplyFailure(
msg,
tc.expExitCode,
)
// new actor balance will only exist if message was applied successfully.
if tc.expExitCode.IsSuccess() {
td.AssertBalance(tc.newActorAddr, tc.newActorInitBal)
td.AssertBalance(existingAccountAddr, big_spec.Sub(big_spec.Sub(tc.existingActorBal, result.Receipt.GasUsed.Big()), tc.newActorInitBal))
}
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}()
if err != nil {
return err
}
}
return nil
}
func MessageTest_InitActorSequentialIDAddressCreate() error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
var initialBal = abi_spec.NewTokenAmount(200_000_000_000)
var toSend = abi_spec.NewTokenAmount(10_000)
sender, _ := td.NewAccountActor(drivers.SECP, initialBal)
receiver, receiverID := td.NewAccountActor(drivers.SECP, initialBal)
firstPaychAddr := chain.MustNewIDAddr(chain.MustIdFromAddress(receiverID) + 1)
secondPaychAddr := chain.MustNewIDAddr(chain.MustIdFromAddress(receiverID) + 2)
firstInitRet := td.ComputeInitActorExecReturn(sender, 0, 0, firstPaychAddr)
secondInitRet := td.ComputeInitActorExecReturn(sender, 1, 0, secondPaychAddr)
preroot := td.GetStateRoot()
msg1 := td.MessageProducer.CreatePaymentChannelActor(sender, receiver, chain.Value(toSend), chain.Nonce(0))
td.ApplyExpect(
msg1,
chain.MustSerialize(&firstInitRet),
)
b1, err := msg1.Serialize()
if err != nil {
return err
}
v.ApplyMessages = append(v.ApplyMessages, b1)
msg2 := td.MessageProducer.CreatePaymentChannelActor(sender, receiver, chain.Value(toSend), chain.Nonce(1))
td.ApplyExpect(
msg2,
chain.MustSerialize(&secondInitRet),
)
b2, err := msg2.Serialize()
if err != nil {
return err
}
v.ApplyMessages = append(v.ApplyMessages, b2)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}
func newEmptyMessageVector() TestVector {
return TestVector{
Class: ClassMessage,
Selector: "",
Meta: &Metadata{
ID: "TK",
Version: "TK",
Gen: GenerationData{
Source: "TK",
Version: "TK",
},
},
Pre: &Preconditions{
StateTree: &StateTree{},
},
Post: &Postconditions{
StateTree: &StateTree{},
},
}
}

View File

@ -0,0 +1,345 @@
package main
import (
"encoding/json"
"os"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
big_spec "github.com/filecoin-project/specs-actors/actors/abi/big"
paych_spec "github.com/filecoin-project/specs-actors/actors/builtin/paych"
crypto_spec "github.com/filecoin-project/specs-actors/actors/crypto"
exitcode_spec "github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/filecoin-project/oni/tvx/chain"
"github.com/filecoin-project/oni/tvx/drivers"
)
func MessageTest_MessageApplicationEdgecases() error {
var aliceBal = abi_spec.NewTokenAmount(1_000_000_000_000)
var transferAmnt = abi_spec.NewTokenAmount(10)
err := func(testname string) error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
preroot := td.GetStateRoot()
alice, _ := td.NewAccountActor(drivers.SECP, aliceBal)
msg := td.MessageProducer.Transfer(alice, alice, chain.Value(transferAmnt), chain.Nonce(0), chain.GasPrice(1), chain.GasLimit(8))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
td.ApplyFailure(
msg,
exitcode_spec.SysErrOutOfGas)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}("fail to cover gas cost for message receipt on chain")
if err != nil {
return err
}
err = func(testname string) error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
preroot := td.GetStateRoot()
alice, _ := td.NewAccountActor(drivers.SECP, aliceBal)
// Expect Message application to fail due to lack of gas
td.ApplyFailure(
td.MessageProducer.Transfer(alice, alice, chain.Value(transferAmnt), chain.Nonce(0), chain.GasPrice(10), chain.GasLimit(1)),
exitcode_spec.SysErrOutOfGas)
// Expect Message application to fail due to lack of gas when sender is unknown
unknown := chain.MustNewIDAddr(10000000)
msg := td.MessageProducer.Transfer(unknown, alice, chain.Value(transferAmnt), chain.Nonce(0), chain.GasPrice(10), chain.GasLimit(1))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
td.ApplyFailure(
msg,
exitcode_spec.SysErrOutOfGas)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}("not enough gas to pay message on-chain-size cost")
if err != nil {
return err
}
err = func(testname string) error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
preroot := td.GetStateRoot()
alice, _ := td.NewAccountActor(drivers.SECP, aliceBal)
aliceNonce := uint64(0)
aliceNonceF := func() uint64 {
defer func() { aliceNonce++ }()
return aliceNonce
}
newAccountA := chain.MustNewSECP256K1Addr("1")
msg := td.MessageProducer.Transfer(alice, newAccountA, chain.Value(transferAmnt), chain.Nonce(aliceNonceF()))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
// get the "true" gas cost of applying the message
result := td.ApplyOk(msg)
// decrease the gas cost by `gasStep` for each apply and ensure `SysErrOutOfGas` is always returned.
trueGas := int64(result.GasUsed())
gasStep := int64(trueGas / 100)
newAccountB := chain.MustNewSECP256K1Addr("2")
for tryGas := trueGas - gasStep; tryGas > 0; tryGas -= gasStep {
msg := td.MessageProducer.Transfer(alice, newAccountB, chain.Value(transferAmnt), chain.Nonce(aliceNonceF()), chain.GasPrice(1), chain.GasLimit(tryGas))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
td.ApplyFailure(
msg,
exitcode_spec.SysErrOutOfGas,
)
}
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}("fail not enough gas to cover account actor creation")
if err != nil {
return err
}
err = func(testname string) error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
preroot := td.GetStateRoot()
alice, _ := td.NewAccountActor(drivers.SECP, aliceBal)
msg := td.MessageProducer.Transfer(alice, alice, chain.Value(transferAmnt), chain.Nonce(1))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
// Expect Message application to fail due to callseqnum being invalid: 1 instead of 0
td.ApplyFailure(
msg,
exitcode_spec.SysErrSenderStateInvalid)
unknown := chain.MustNewIDAddr(10000000)
msg = td.MessageProducer.Transfer(unknown, alice, chain.Value(transferAmnt), chain.Nonce(1))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
// Expect message application to fail due to unknow actor when call seq num is also incorrect
td.ApplyFailure(
msg,
exitcode_spec.SysErrSenderInvalid)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}("invalid actor CallSeqNum")
if err != nil {
return err
}
err = func(testname string) error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
preroot := td.GetStateRoot()
const pcTimeLock = abi_spec.ChainEpoch(10)
const pcLane = uint64(123)
const pcNonce = uint64(1)
var pcAmount = big_spec.NewInt(10)
var initialBal = abi_spec.NewTokenAmount(200_000_000_000)
var toSend = abi_spec.NewTokenAmount(10_000)
var pcSig = &crypto_spec.Signature{
Type: crypto_spec.SigTypeBLS,
Data: []byte("Grrr im an invalid signature, I cause panics in the payment channel actor"),
}
// will create and send on payment channel
sender, _ := td.NewAccountActor(drivers.SECP, initialBal)
// will be receiver on paych
receiver, receiverID := td.NewAccountActor(drivers.SECP, initialBal)
// the _expected_ address of the payment channel
paychAddr := chain.MustNewIDAddr(chain.MustIdFromAddress(receiverID) + 1)
createRet := td.ComputeInitActorExecReturn(sender, 0, 0, paychAddr)
msg := td.MessageProducer.CreatePaymentChannelActor(sender, receiver, chain.Value(toSend), chain.Nonce(0))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
td.ApplyExpect(
msg,
chain.MustSerialize(&createRet))
msg = td.MessageProducer.PaychUpdateChannelState(sender, paychAddr, &paych_spec.UpdateChannelStateParams{
Sv: paych_spec.SignedVoucher{
ChannelAddr: paychAddr,
TimeLockMin: pcTimeLock,
TimeLockMax: pcTimeLock,
SecretPreimage: nil,
Extra: nil,
Lane: pcLane,
Nonce: pcNonce,
Amount: pcAmount,
MinSettleHeight: 0,
Merges: nil,
Signature: pcSig, // construct with invalid signature
},
}, chain.Nonce(1), chain.Value(big_spec.Zero()))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
// message application fails due to invalid argument (signature).
td.ApplyFailure(
msg,
exitcode_spec.ErrIllegalArgument)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}("abort during actor execution")
if err != nil {
return err
}
err = func(testname string) error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
preroot := td.GetStateRoot()
alice, _ := td.NewAccountActor(drivers.SECP, aliceBal)
msg := td.MessageProducer.MarketComputeDataCommitment(alice, alice, nil, chain.Nonce(0))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
// message application fails because ComputeDataCommitment isn't defined
// on the recipient actor
td.ApplyFailure(
msg,
exitcode_spec.SysErrInvalidMethod)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}("invalid method for receiver")
if err != nil {
return err
}
err = func(testname string) error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
preroot := td.GetStateRoot()
alice, _ := td.NewAccountActor(drivers.SECP, aliceBal)
// Sending a message to non-existent ID address must produce an error.
unknownA := chain.MustNewIDAddr(10000000)
msg := td.MessageProducer.Transfer(alice, unknownA, chain.Value(transferAmnt), chain.Nonce(0))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
td.ApplyFailure(
msg,
exitcode_spec.SysErrInvalidReceiver)
// Sending a message to non-existing actor address must produce an error.
unknownB := chain.MustNewActorAddr("1234")
msg = td.MessageProducer.Transfer(alice, unknownB, chain.Value(transferAmnt), chain.Nonce(1))
v.ApplyMessages = append(v.ApplyMessages, chain.MustSerialize(msg))
td.ApplyFailure(
msg,
exitcode_spec.SysErrInvalidReceiver)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}("receiver ID/Actor address does not exist")
if err != nil {
return err
}
return nil
// TODO more tests:
// - missing/mismatched params for receiver
// - various out-of-gas cases
}