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:
parent
17f0b4a2e1
commit
5353210814
18
tvx/chain/account.go
Normal file
18
tvx/chain/account.go
Normal 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
56
tvx/chain/address.go
Normal 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
19
tvx/chain/cron.go
Normal 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
18
tvx/chain/init_.go
Normal 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
47
tvx/chain/market.go
Normal 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...)
|
||||
}
|
94
tvx/chain/message_producer.go
Normal file
94
tvx/chain/message_producer.go
Normal 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
85
tvx/chain/miner.go
Normal 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
42
tvx/chain/multisig.go
Normal 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
27
tvx/chain/paych.go
Normal 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
49
tvx/chain/power.go
Normal 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
18
tvx/chain/puppet.go
Normal 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
28
tvx/chain/reward.go
Normal 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...)
|
||||
}
|
38
tvx/chain/serialization.go
Normal file
38
tvx/chain/serialization.go
Normal 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
52
tvx/chain/sugar.go
Normal 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
14
tvx/chain/types/block.go
Normal 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
|
||||
}
|
17
tvx/chain/types/executioncontext.go
Normal file
17
tvx/chain/types/executioncontext.go
Normal 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}
|
||||
}
|
20
tvx/chain/types/receipt.go
Normal file
20
tvx/chain/types/receipt.go
Normal 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))
|
||||
}
|
64
tvx/chain/types/results.go
Normal file
64
tvx/chain/types/results.go
Normal 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
|
||||
}
|
15
tvx/chain/types/sectors.go
Normal file
15
tvx/chain/types/sectors.go
Normal 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
52
tvx/chain/wallet/bls.go
Normal 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
57
tvx/chain/wallet/secp.go
Normal 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
113
tvx/chain/wallet/wallet.go
Normal 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
150
tvx/drivers/applier.go
Normal 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
21
tvx/drivers/config.go
Normal 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
|
||||
}
|
28
tvx/drivers/dummy_testingt.go
Normal file
28
tvx/drivers/dummy_testingt.go
Normal 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
105
tvx/drivers/key_manager.go
Normal 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
|
||||
}
|
64
tvx/drivers/mock_sector_builder.go
Normal file
64
tvx/drivers/mock_sector_builder.go
Normal 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
44
tvx/drivers/randomness.go
Normal 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
206
tvx/drivers/state_driver.go
Normal 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))
|
||||
}
|
198
tvx/drivers/state_wrapper.go
Normal file
198
tvx/drivers/state_wrapper.go
Normal 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
110
tvx/drivers/syscall.go
Normal 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
567
tvx/drivers/test_driver.go
Normal 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
|
||||
}
|
201
tvx/drivers/tipset_message_producer.go
Normal file
201
tvx/drivers/tipset_message_producer.go
Normal 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
39
tvx/drivers/various.go
Normal 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
|
||||
}
|
18
tvx/go.mod
18
tvx/go.mod
@ -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
|
||||
|
40
tvx/go.sum
40
tvx/go.sum
@ -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=
|
||||
|
@ -33,6 +33,7 @@ func main() {
|
||||
extractMsgCmd,
|
||||
execLotusCmd,
|
||||
examineCmd,
|
||||
suiteMessagesCmd,
|
||||
},
|
||||
}
|
||||
|
||||
|
216
tvx/messages_create_actor.go
Normal file
216
tvx/messages_create_actor.go
Normal 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{},
|
||||
},
|
||||
}
|
||||
}
|
345
tvx/messages_message_application.go
Normal file
345
tvx/messages_message_application.go
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user