Documentation
¶
Overview ¶
Package solo is a development tool to write unit tests for IOTA Smart Contracts (ISC).
A development tool ¶
The package is intended for developers of smart contracts as well as contributors to the development of the ISC and the Wasp node itself.
Normally, the smart contract is developed and tested in the 'solo' environment before trying it out on the network of Wasp nodes. Running and testing the smart contract on 'solo' does not require to run the Wasp nodes nor committee of nodes: just ordinary 'go test' environment.
Native environment ¶
'solo' shares the same code of Virtual Machine with the Wasp node. This guarantees that smart contract programs can later be deployed on chains which are run by the network of Wasp nodes without any modifications.
The 'solo' environment uses in-memory UTXO ledger to validate and store transactions. The UTXODB mocks the Shimmer UTXO ledger, it uses same value transaction structure, colored tokens, signature schemes as well as transaction and signature validation as in the Value Tangle of Shimmer. The only difference with the Value Tangle is that UTXODB provides full synchronicity of ledger updates.
The virtual state (key/value database) in 'solo' is an in-memory database. It provides exactly the same interface of access to it as the database of the Wasp node.
Example test ¶
The following example deploys chain and retrieves basic info from the deployed chain. It is expected 4 core contracts deployed on it by default and the test prints them.
func TestSolo1(t *testing.T) {
env := solo.New(t, false, false)
chain := env.NewChain(nil, "ex1")
chainInfo, coreContracts := chain.GetInfo() // calls view root::GetInfo
require.EqualValues(t, 4, len(coreContracts)) // 4 core contracts deployed by default
t.Logf("chainID: %s", chainInfo.ChainID)
t.Logf("chain owner ID: %s", chainInfo.ChainOwnerID)
for hname, rec := range coreContracts {
t.Logf(" Core contract '%s': %s", rec.Name, isc.NewContractID(chain.ChainID, hname))
}
}
will produce the following output:
=== RUN TestSolo1 34:37.415 INFO TestSolo1 solo/solo.go:153 deploying new chain 'ex1' 34:37.419 INFO TestSolo1.ex1 vmcontext/runreq.go:177 eventlog -> '[req] [0]Ei4d6oUbcgSPnmpTupeLaTNoNf1hRu8ZfZfmw2KFKzZm: Ok' 34:37.420 INFO TestSolo1.ex1 solo/run.go:75 state transition #0 --> #1. Requests in the block: 1. Posted: 0 34:37.420 INFO TestSolo1 solo/clock.go:44 ClockStep: logical clock advanced by 1ms 34:37.420 INFO TestSolo1.ex1 solo/solo.go:233 chain 'ex1' deployed. Chain ID: aEbE2vX6jrGhQ3AKHCPmQmn2qa11CpCRzaEgtVJRAje3 34:37.420 INFO TestSolo1.ex1 solo/req.go:145 callView: root::getChainInfo solo_test.go:18: chainID: aEbE2vX6jrGhQ3AKHCPmQmn2qa11CpCRzaEgtVJRAje3 solo_test.go:19: chain owner ID: A/UrYEv4Yh7WU1M29cKq73tb2CUx8EYXfJt6JZn5srw19U solo_test.go:21: Core contract 'accounts': aEbE2vX6jrGhQ3AKHCPmQmn2qa11CpCRzaEgtVJRAje3::3c4b5e02 solo_test.go:21: Core contract 'blob': aEbE2vX6jrGhQ3AKHCPmQmn2qa11CpCRzaEgtVJRAje3::fd91bc63 solo_test.go:21: Core contract 'root': aEbE2vX6jrGhQ3AKHCPmQmn2qa11CpCRzaEgtVJRAje3::cebf5908 solo_test.go:21: Core contract 'eventlog': aEbE2vX6jrGhQ3AKHCPmQmn2qa11CpCRzaEgtVJRAje3::661aa7d8 --- PASS: TestSolo1 (0.01s)
Index ¶
- Constants
- Variables
- func EVMCallDataFromArtifacts(t require.TestingT, abiJSON string, bytecode []byte, args ...any) (abi.ABI, []byte)
- func EthereumAccountByIndex(i int) (*ecdsa.PrivateKey, common.Address)
- func NewEthereumAccount() (*ecdsa.PrivateKey, common.Address)
- type CallParams
- func (r *CallParams) AddAllowance(allowance *isc.Assets) *CallParams
- func (r *CallParams) AddAllowanceBaseTokens(amount coin.Value) *CallParams
- func (r *CallParams) AddAllowanceCoins(coinType coin.Type, amount coin.Value) *CallParams
- func (r *CallParams) AddAllowanceObject(obj isc.IotaObject) *CallParams
- func (r *CallParams) AddBaseTokens(amount coin.Value) *CallParams
- func (r *CallParams) AddCoin(coinType coin.Type, amount coin.Value) *CallParams
- func (r *CallParams) AddFungibleTokens(ftokens isc.CoinBalances) *CallParams
- func (r *CallParams) AddObject(obj isc.IotaObject) *CallParams
- func (r *CallParams) GasBudget() uint64
- func (r *CallParams) NewRequestOffLedger(ch *Chain, keyPair *cryptolib.KeyPair) isc.OffLedgerRequest
- func (r *CallParams) NewRequestOnLedger(ch *Chain, keyPair *cryptolib.KeyPair) (isc.OnLedgerRequest, error)
- func (r *CallParams) WithAllowance(allowance *isc.Assets) *CallParams
- func (r *CallParams) WithAssets(assets *isc.Assets) *CallParams
- func (r *CallParams) WithFungibleTokens(ftokens isc.CoinBalances) *CallParams
- func (r *CallParams) WithGasBudget(gasBudget uint64) *CallParams
- func (r *CallParams) WithMaxAffordableGasBudget() *CallParams
- func (r *CallParams) WithNonce(nonce uint64) *CallParams
- func (r *CallParams) WithSender(sender *cryptolib.Address) *CallParams
- func (r *CallParams) WithTargetContract(contract any) *CallParams
- type Chain
- func (ch *Chain) AddMigration(m migrations.Migration)
- func (ch *Chain) AdminAddress() *cryptolib.Address
- func (ch *Chain) AdminAgentID() isc.AgentID
- func (ch *Chain) AnchorOwnerAddress() *cryptolib.Address
- func (ch *Chain) AssertL2BaseTokens(agentID isc.AgentID, bal coin.Value)
- func (ch *Chain) AssertL2Coins(agentID isc.AgentID, coinType coin.Type, expected coin.Value)
- func (ch *Chain) AssertL2TotalBaseTokens(bal coin.Value)
- func (ch *Chain) AssertL2TotalCoins(coinType coin.Type, bal coin.Value)
- func (ch *Chain) CallView(msg isc.Message) (isc.CallArguments, error)
- func (ch *Chain) CallViewAtState(chainState state.State, msg isc.Message) (isc.CallArguments, error)
- func (ch *Chain) CallViewByHname(msg isc.Message) (isc.CallArguments, error)
- func (ch *Chain) CallViewEx(c, ep string, params ...isc.CallArguments) (isc.CallArguments, error)
- func (ch *Chain) CallViewWithContract(contract any, msg isc.Message) (isc.CallArguments, error)
- func (ch *Chain) CheckAccountLedger()
- func (ch *Chain) CheckChain()
- func (ch *Chain) DeployEVMContract(creator *ecdsa.PrivateKey, abiJSON string, bytecode []byte, value *big.Int, ...) (common.Address, abi.ABI)
- func (ch *Chain) DepositAssetsToL2(assets *isc.Assets, user *cryptolib.KeyPair) error
- func (ch *Chain) DepositBaseTokensToL2(amount coin.Value, user *cryptolib.KeyPair) error
- func (ch *Chain) DumpAccounts() string
- func (ch *Chain) EVM() *jsonrpc.EVMChain
- func (ch *Chain) EstimateGas(req isc.Request) (result *vm.RequestResult)
- func (ch *Chain) EstimateGasOffLedger(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, *blocklog.RequestReceipt, error)
- func (ch *Chain) EstimateGasOnLedger(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, *blocklog.RequestReceipt, error)
- func (ch *Chain) EstimateOnLedgerRequest(dryRunRes *iotajsonrpc.DryRunTransactionBlockResponse) (result *vm.RequestResult, err error)
- func (ch *Chain) EthereumAccountByIndexWithL2Funds(i int, baseTokens ...coin.Value) (*ecdsa.PrivateKey, common.Address)
- func (ch *Chain) EthereumAccountByIndexWithL2FundsRandDepositor(i int, baseTokens ...coin.Value) (*ecdsa.PrivateKey, common.Address)
- func (ch *Chain) FindContract(scName string) (*root.ContractRecord, error)
- func (ch *Chain) GetAnchor(stateIndex uint32) (*isc.StateAnchor, error)
- func (ch *Chain) GetBlockInfo(blockIndex ...uint32) (*blocklog.BlockInfo, error)
- func (ch *Chain) GetBlockProof(blockIndex uint32) (*blocklog.BlockInfo, *trie.MerkleProof, error)
- func (ch *Chain) GetContractStateCommitment(hn isc.Hname) ([]byte, error)
- func (ch *Chain) GetErrorMessageFormat(code isc.VMErrorCode) (string, error)
- func (ch *Chain) GetEventsForBlock(blockIndex uint32) ([]*isc.Event, error)
- func (ch *Chain) GetEventsForRequest(reqID isc.RequestID) ([]*isc.Event, error)
- func (ch *Chain) GetGasFeePolicy() *gas.FeePolicy
- func (ch *Chain) GetGasLimits() *gas.Limits
- func (ch *Chain) GetInfo() (isc.ChainID, isc.AgentID, map[isc.Hname]*root.ContractRecord)
- func (ch *Chain) GetL1Commitment() *state.L1Commitment
- func (ch *Chain) GetL1RequestData(objectID iotago.ObjectID) isc.OnLedgerRequest
- func (ch *Chain) GetL2FundsFromFaucet(agentID isc.AgentID, baseTokens ...coin.Value)
- func (ch *Chain) GetL2FundsFromFaucetWithDepositor(agentID isc.AgentID, depositorSeed []byte, baseTokens ...coin.Value)
- func (ch *Chain) GetLatestAnchor() *isc.StateAnchor
- func (ch *Chain) GetLatestAnchorWithBalances() (*isc.StateAnchor, *isc.Assets)
- func (ch *Chain) GetLatestBlockInfo() *blocklog.BlockInfo
- func (ch *Chain) GetLatestGasCoin() *coin.CoinWithRef
- func (ch *Chain) GetMerkleProof(scHname isc.Hname, key []byte) *trie.MerkleProof
- func (ch *Chain) GetMerkleProofRaw(key []byte) *trie.MerkleProof
- func (ch *Chain) GetRequestIDsForBlock(blockIndex uint32) []isc.RequestID
- func (ch *Chain) GetRequestReceipt(reqID isc.RequestID) (*blocklog.RequestReceipt, bool)
- func (ch *Chain) GetRequestReceiptsForBlock(blockIndex ...uint32) []*blocklog.RequestReceipt
- func (ch *Chain) GetRequestReceiptsForBlockRange(fromBlockIndex, toBlockIndex uint32) []*blocklog.RequestReceipt
- func (ch *Chain) GetRootCommitment() trie.Hash
- func (ch *Chain) HasL2Object(agentID isc.AgentID, objID iotago.ObjectID) bool
- func (ch *Chain) ID() isc.ChainID
- func (ch *Chain) IsRequestProcessed(reqID isc.RequestID) bool
- func (ch *Chain) L1L2Funds(addr *cryptolib.Address) *L1L2CoinBalances
- func (ch *Chain) L2Accounts() []isc.AgentID
- func (ch *Chain) L2Assets(agentID isc.AgentID) *isc.Assets
- func (ch *Chain) L2AssetsAtStateIndex(agentID isc.AgentID, stateIndex uint32) *isc.Assets
- func (ch *Chain) L2BaseTokens(agentID isc.AgentID) coin.Value
- func (ch *Chain) L2BaseTokensAtStateIndex(agentID isc.AgentID, stateIndex uint32) coin.Value
- func (ch *Chain) L2CoinBalance(agentID isc.AgentID, coinType coin.Type) coin.Value
- func (ch *Chain) L2CommonAccountAssets() *isc.Assets
- func (ch *Chain) L2CommonAccountBaseTokens() coin.Value
- func (ch *Chain) L2CommonAccountNativeTokens(coinType coin.Type) coin.Value
- func (ch *Chain) L2Ledger() map[string]*isc.Assets
- func (ch *Chain) L2LedgerString() string
- func (ch *Chain) L2Objects(agentID isc.AgentID) []isc.IotaObject
- func (ch *Chain) L2TotalAssets() *isc.Assets
- func (ch *Chain) L2TotalBaseTokens() coin.Value
- func (ch *Chain) LastReceipt() *isc.Receipt
- func (ch *Chain) LatestBlock() state.Block
- func (ch *Chain) LatestBlockIndex() uint32
- func (ch *Chain) LatestState() (state.State, error)
- func (ch *Chain) Log() log.Logger
- func (ch *Chain) MustDepositBaseTokensToL2(amount coin.Value, user *cryptolib.KeyPair)
- func (ch *Chain) NewEthereumAccountWithL2Funds(baseTokens ...coin.Value) (*ecdsa.PrivateKey, common.Address)
- func (ch *Chain) Nonce(agentID isc.AgentID) uint64
- func (ch *Chain) PostEthereumTransaction(tx *types.Transaction) (isc.CallArguments, error)
- func (ch *Chain) PostRequestOffLedger(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, error)
- func (ch *Chain) PostRequestSync(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, error)
- func (ch *Chain) PostRequestSyncExt(callParams *CallParams, keyPair *cryptolib.KeyPair) (req isc.OnLedgerRequest, l1Res *iotajsonrpc.IotaTransactionBlockResponse, ...)
- func (ch *Chain) PostRequestSyncTx(req *CallParams, keyPair *cryptolib.KeyPair) (onLedregReq isc.OnLedgerRequest, ...)
- func (ch *Chain) Processors() *processors.Config
- func (ch *Chain) ResolveVMError(e *isc.UnresolvedVMError) *isc.VMError
- func (ch *Chain) RunAllReceivedRequests(maxRequestsInBlock int) int
- func (ch *Chain) RunOffLedgerRequest(r isc.Request) (*iotajsonrpc.IotaTransactionBlockResponse, isc.CallArguments, error)
- func (ch *Chain) RunOffLedgerRequests(reqs []isc.Request) (*iotajsonrpc.IotaTransactionBlockResponse, []*vm.RequestResult)
- func (ch *Chain) RunRequestBatch(maxRequestsInBlock int) (*iotajsonrpc.IotaTransactionBlockResponse, []*vm.RequestResult)
- func (ch *Chain) RunRequestsSync(reqs []isc.Request) (*iotajsonrpc.IotaTransactionBlockResponse, []*vm.RequestResult)
- func (ch *Chain) SaveDB(path string)
- func (ch *Chain) SendFromL1ToL2Account(toSend isc.CoinBalances, extraDeposit coin.Value, target isc.AgentID, ...) error
- func (ch *Chain) SendFromL1ToL2AccountBaseTokens(toSend, extraDeposit coin.Value, target isc.AgentID, user *cryptolib.KeyPair) error
- func (ch *Chain) SendFromL2ToL2Account(transfer *isc.Assets, target isc.AgentID, user *cryptolib.KeyPair) error
- func (ch *Chain) SendFromL2ToL2AccountBaseTokens(baseTokens coin.Value, target isc.AgentID, user *cryptolib.KeyPair) error
- func (ch *Chain) SendFromL2ToL2AccountNativeTokens(coinType coin.Type, target isc.AgentID, amount coin.Value, ...) error
- func (ch *Chain) SendRequest(req *CallParams, keyPair *cryptolib.KeyPair) (isc.OnLedgerRequest, *iotajsonrpc.IotaTransactionBlockResponse, error)
- func (ch *Chain) SendRequestWithL1GasBudget(req *CallParams, keyPair *cryptolib.KeyPair, l1GasBudget uint64) (isc.OnLedgerRequest, *iotajsonrpc.IotaTransactionBlockResponse, error)
- func (ch *Chain) SetGasFeePolicy(user *cryptolib.KeyPair, fp *gas.FeePolicy)
- func (ch *Chain) SetGasLimits(user *cryptolib.KeyPair, gl *gas.Limits)
- func (ch *Chain) Store() indexedstore.IndexedStore
- func (ch *Chain) String() string
- func (ch *Chain) TransferAllowanceTo(allowance *isc.Assets, targetAccount isc.AgentID, wallet *cryptolib.KeyPair) error
- func (ch *Chain) Withdraw(assets *isc.Assets, user *cryptolib.KeyPair) error
- type ChainSnapshot
- type Context
- type InitOptions
- type L1Config
- type L1L2CoinBalances
- type Snapshot
- type Solo
- func (env *Solo) AdvanceClockBy(step time.Duration)
- func (env *Solo) AssertL1BaseTokens(addr *cryptolib.Address, expected coin.Value)
- func (env *Solo) AssertL1Coins(addr *cryptolib.Address, coinType coin.Type, expected coin.Value)
- func (env *Solo) Ctx() context.Context
- func (env *Solo) GetChainByName(name string) *Chain
- func (env *Solo) GetCoin(id *iotago.ObjectID) *coin.CoinWithRef
- func (env *Solo) GetFundsFromFaucet(target *cryptolib.Address)
- func (env *Solo) GlobalTime() time.Time
- func (env *Solo) ISCMoveClient() *iscmoveclient.Client
- func (env *Solo) ISCPackageID() iotago.PackageID
- func (env *Solo) IotaFaucetURL() string
- func (env *Solo) IterateChainLatestStates(prefix kv.Key, f func(chainID *isc.ChainID, k []byte, v []byte))
- func (env *Solo) IterateChainTrieDBs(f func(chainID *isc.ChainID, k []byte, v []byte))
- func (env *Solo) L1AllCoins(addr *cryptolib.Address) iotajsonrpc.Coins
- func (env *Solo) L1BaseTokenCoins(addr *cryptolib.Address) []*iotajsonrpc.Coin
- func (env *Solo) L1BaseTokens(addr *cryptolib.Address) coin.Value
- func (env *Solo) L1Client() clients.L1Client
- func (env *Solo) L1CoinBalance(addr *cryptolib.Address, coinType coin.Type) coin.Value
- func (env *Solo) L1CoinBalances(addr *cryptolib.Address) isc.CoinBalances
- func (env *Solo) L1CoinInfo(coinType coin.Type) *parameters.IotaCoinInfo
- func (env *Solo) L1Coins(addr *cryptolib.Address, coinType coin.Type) []*iotajsonrpc.Coin
- func (env *Solo) L1DeployCoinPackage(keyPair cryptolib.Signer) (packageID *iotago.PackageID, treasuryCap *iotago.ObjectRef)
- func (env *Solo) L1MintCoin(keyPair cryptolib.Signer, packageID *iotago.PackageID, ...) (coinRef *iotago.ObjectRef)
- func (env *Solo) L1MintObject(owner *cryptolib.KeyPair) isc.IotaObject
- func (env *Solo) L1Params() *parameters.L1Params
- func (env *Solo) LoadSnapshot(fname string) *Snapshot
- func (env *Solo) MustWithWaitForNextVersion(currentRef *iotago.ObjectRef, cb func()) *iotago.ObjectRef
- func (env *Solo) NewChain(depositFundsForAdmin ...bool) *Chain
- func (env *Solo) NewChainExt(chainOriginator *cryptolib.KeyPair, initCommonAccountBaseTokens coin.Value, ...) (*Chain, *isc.StateAnchor)
- func (env *Solo) NewKeyPair(seedOpt ...*cryptolib.Seed) (*cryptolib.KeyPair, *cryptolib.Address)
- func (env *Solo) NewKeyPairFromIndex(index int) *cryptolib.KeyPair
- func (env *Solo) NewKeyPairWithFunds(seed ...*cryptolib.Seed) (*cryptolib.KeyPair, *cryptolib.Address)
- func (env *Solo) NewSeedFromIndex(index int) *cryptolib.Seed
- func (env *Solo) NewSeedFromTestNameAndTimestamp(testName string) *cryptolib.Seed
- func (env *Solo) Publisher() *publisher.Publisher
- func (env *Solo) RestoreSnapshot(snapshot *Snapshot)
- func (env *Solo) SaveSnapshot(snapshot *Snapshot, fname string)
- func (env *Solo) SelectCoinsForGas(addr *cryptolib.Address, targetPTB *iotago.ProgrammableTransaction, ...) []*iotago.ObjectRef
- func (env *Solo) TakeSnapshot() *Snapshot
- func (env *Solo) WaitForNewBalance(address *cryptolib.Address, startBalance coin.Value)
- func (env *Solo) WithWaitForNextVersion(currentRef *iotago.ObjectRef, cb func()) (*iotago.ObjectRef, error)
Constants ¶
const ( DestroyTokensGasBudgetBaseTokens = 1 * isc.Million SendToL2AccountGasBudgetBaseTokens = 1 * isc.Million DestroyFoundryGasBudgetBaseTokens = 1 * isc.Million TransferAllowanceToGasBudgetBaseTokens = 1 * isc.Million )
CreateFoundryGasBudgetBaseTokens always takes 100000 base tokens as gas budget and ftokens for the call
Variables ¶
var ( BaseTokensForL2Gas = gas.FeeFromGasWithGasPerToken(gas.LimitsDefault.MaxGasPerRequest, gas.DefaultGasPerToken) DefaultChainAdminBaseTokens = 2 * BaseTokensForL2Gas )
var EthereumAccounts [10]*ecdsa.PrivateKey
Functions ¶
func EthereumAccountByIndex ¶
func EthereumAccountByIndex(i int) (*ecdsa.PrivateKey, common.Address)
func NewEthereumAccount ¶
func NewEthereumAccount() (*ecdsa.PrivateKey, common.Address)
Types ¶
type CallParams ¶
type CallParams struct {
// contains filtered or unexported fields
}
func NewCallParams ¶
func NewCallParams(msg isc.Message, contract ...any) *CallParams
NewCallParams creates a structure that wraps in one object call parameters, used in PostRequestSync and CallView
func NewCallParamsEx ¶
func NewCallParamsEx(c, ep string, params ...isc.CallArguments) *CallParams
NewCallParamsEx is a shortcut for NewCallParams
func (*CallParams) AddAllowance ¶
func (r *CallParams) AddAllowance(allowance *isc.Assets) *CallParams
func (*CallParams) AddAllowanceBaseTokens ¶
func (r *CallParams) AddAllowanceBaseTokens(amount coin.Value) *CallParams
func (*CallParams) AddAllowanceCoins ¶
func (r *CallParams) AddAllowanceCoins(coinType coin.Type, amount coin.Value) *CallParams
func (*CallParams) AddAllowanceObject ¶
func (r *CallParams) AddAllowanceObject(obj isc.IotaObject) *CallParams
func (*CallParams) AddBaseTokens ¶
func (r *CallParams) AddBaseTokens(amount coin.Value) *CallParams
AddBaseTokens adds base tokens to be sent (only applicable when the call is made via on-ledger request)
func (*CallParams) AddCoin ¶
func (r *CallParams) AddCoin(coinType coin.Type, amount coin.Value) *CallParams
AddCoin adds a coin to be sent (only applicable when the call is made via on-ledger request)
func (*CallParams) AddFungibleTokens ¶
func (r *CallParams) AddFungibleTokens(ftokens isc.CoinBalances) *CallParams
AddFungibleTokens adds tokens to be sent (only applicable when the call is made via on-ledger request)
func (*CallParams) AddObject ¶
func (r *CallParams) AddObject(obj isc.IotaObject) *CallParams
AddObject adds an object to be sent (only applicable when the call is made via on-ledger request)
func (*CallParams) GasBudget ¶
func (r *CallParams) GasBudget() uint64
func (*CallParams) NewRequestOffLedger ¶
func (r *CallParams) NewRequestOffLedger(ch *Chain, keyPair *cryptolib.KeyPair) isc.OffLedgerRequest
NewRequestOffLedger creates off-ledger request from parameters
func (*CallParams) NewRequestOnLedger ¶
func (r *CallParams) NewRequestOnLedger(ch *Chain, keyPair *cryptolib.KeyPair) (isc.OnLedgerRequest, error)
NewRequestOnLedger creates an on-ledger request without sending it to L1. It is intended mainly for estimating gas.
func (*CallParams) WithAllowance ¶
func (r *CallParams) WithAllowance(allowance *isc.Assets) *CallParams
func (*CallParams) WithAssets ¶
func (r *CallParams) WithAssets(assets *isc.Assets) *CallParams
WithAssets sets the assets to be sent (only applicable when the call is made via on-ledger request)
func (*CallParams) WithFungibleTokens ¶
func (r *CallParams) WithFungibleTokens(ftokens isc.CoinBalances) *CallParams
WithFungibleTokens sets the tokens to be sent (only applicable when the call is made via on-ledger request)
func (*CallParams) WithGasBudget ¶
func (r *CallParams) WithGasBudget(gasBudget uint64) *CallParams
func (*CallParams) WithMaxAffordableGasBudget ¶
func (r *CallParams) WithMaxAffordableGasBudget() *CallParams
func (*CallParams) WithNonce ¶
func (r *CallParams) WithNonce(nonce uint64) *CallParams
func (*CallParams) WithSender ¶
func (r *CallParams) WithSender(sender *cryptolib.Address) *CallParams
func (*CallParams) WithTargetContract ¶
func (r *CallParams) WithTargetContract(contract any) *CallParams
type Chain ¶
type Chain struct {
// Env is a pointer to the global structure of the 'solo' test
Env *Solo
// contains filtered or unexported fields
}
Chain represents state of individual chain. There may be several parallel instances of the chain in the 'solo' test
func (*Chain) AddMigration ¶
func (ch *Chain) AddMigration(m migrations.Migration)
func (*Chain) AdminAddress ¶
func (*Chain) AdminAgentID ¶
func (*Chain) AnchorOwnerAddress ¶
func (*Chain) AssertL2BaseTokens ¶
func (*Chain) AssertL2Coins ¶
func (*Chain) AssertL2TotalBaseTokens ¶
func (*Chain) AssertL2TotalCoins ¶
func (*Chain) CallViewAtState ¶
func (*Chain) CallViewByHname ¶
func (*Chain) CallViewEx ¶
func (ch *Chain) CallViewEx(c, ep string, params ...isc.CallArguments) (isc.CallArguments, error)
CallViewEx is a shortcut for CallView
func (*Chain) CallViewWithContract ¶
func (*Chain) CheckAccountLedger ¶
func (ch *Chain) CheckAccountLedger()
CheckAccountLedger checks the integrity of the on-chain ledger. Sum of all accounts must be equal to total ftokens
func (*Chain) CheckChain ¶
func (ch *Chain) CheckChain()
CheckChain checks fundamental integrity of the chain
func (*Chain) DeployEVMContract ¶
func (ch *Chain) DeployEVMContract(creator *ecdsa.PrivateKey, abiJSON string, bytecode []byte, value *big.Int, args ...any) (common.Address, abi.ABI)
DeployEVMContract deploys an evm contract on the chain
func (*Chain) DepositAssetsToL2 ¶
DepositAssetsToL2 deposits ftokens on user's on-chain account, if user is nil, then chain admin is assigned
func (*Chain) DepositBaseTokensToL2 ¶
DepositBaseTokensToL2 deposits ftokens on user's on-chain account
func (*Chain) DumpAccounts ¶
DumpAccounts dumps all account balances into the human-readable string
func (*Chain) EstimateGas ¶
func (ch *Chain) EstimateGas(req isc.Request) (result *vm.RequestResult)
func (*Chain) EstimateGasOffLedger ¶
func (ch *Chain) EstimateGasOffLedger(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, *blocklog.RequestReceipt, error)
EstimateGasOffLedger executes the given on-ledger request without committing any changes in the ledger. It returns the amount of gas consumed. WARNING: Gas estimation is just an "estimate", there is no guarantees that the real call will bear the same cost, due to the turing-completeness of smart contracts
func (*Chain) EstimateGasOnLedger ¶
func (ch *Chain) EstimateGasOnLedger(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, *blocklog.RequestReceipt, error)
EstimateGasOnLedger executes the given on-ledger request without committing any changes in the ledger. It returns the amount of gas consumed. WARNING: Gas estimation is just an "estimate", there is no guarantees that the real call will bear the same cost, due to the turing-completeness of smart contracts TODO only a senderAddr, not a keyPair should be necessary to estimate (it definitely shouldn't fallback to the chain originator)
func (*Chain) EstimateOnLedgerRequest ¶
func (ch *Chain) EstimateOnLedgerRequest(dryRunRes *iotajsonrpc.DryRunTransactionBlockResponse) (result *vm.RequestResult, err error)
EstimateOnLedgerRequest estimates total Gas Fee, which is composed of L1 gas fee (user spent on creating onledger request) and L2 gas fee (wasp gas fee for proccesing request on L2)
func (*Chain) EthereumAccountByIndexWithL2Funds ¶
func (*Chain) EthereumAccountByIndexWithL2FundsRandDepositor ¶
func (*Chain) FindContract ¶
func (ch *Chain) FindContract(scName string) (*root.ContractRecord, error)
FindContract is a view call to the 'root' smart contract on the chain. It returns blobCache record of the deployed smart contract with the given name
func (*Chain) GetBlockInfo ¶
GetBlockInfo return BlockInfo for the particular block index in the chain
func (*Chain) GetBlockProof ¶
GetBlockProof returns Merkle proof of the key in the state
func (*Chain) GetContractStateCommitment ¶
GetContractStateCommitment returns commitment to the state of the specific contract, if possible
func (*Chain) GetErrorMessageFormat ¶
func (ch *Chain) GetErrorMessageFormat(code isc.VMErrorCode) (string, error)
func (*Chain) GetEventsForBlock ¶
GetEventsForBlock calls the view in the 'blocklog' core smart contract to retrieve events for a given block.
func (*Chain) GetEventsForRequest ¶
GetEventsForRequest calls the view in the 'blocklog' core smart contract to retrieve events for a given request.
func (*Chain) GetGasFeePolicy ¶
func (*Chain) GetGasLimits ¶
func (*Chain) GetInfo ¶
GetInfo returns information about the chain:
- chainID
- agentID of the chain admin
- list of contracts deployed on the chain
func (*Chain) GetL1Commitment ¶
func (ch *Chain) GetL1Commitment() *state.L1Commitment
GetL1Commitment returns state commitment taken from the anchor output
func (*Chain) GetL1RequestData ¶
func (ch *Chain) GetL1RequestData(objectID iotago.ObjectID) isc.OnLedgerRequest
func (*Chain) GetL2FundsFromFaucet ¶
func (*Chain) GetL2FundsFromFaucetWithDepositor ¶
func (ch *Chain) GetL2FundsFromFaucetWithDepositor(agentID isc.AgentID, depositorSeed []byte, baseTokens ...coin.Value)
GetL2FundsFromFaucetWithDepositor is for multiple concurrent calls scenarios. This function uses given depositorSeed to generate the depositor to call TransferAllowanceTo()
func (*Chain) GetLatestAnchor ¶
func (ch *Chain) GetLatestAnchor() *isc.StateAnchor
func (*Chain) GetLatestAnchorWithBalances ¶
func (ch *Chain) GetLatestAnchorWithBalances() (*isc.StateAnchor, *isc.Assets)
func (*Chain) GetLatestBlockInfo ¶
GetLatestBlockInfo return BlockInfo for the latest block in the chain
func (*Chain) GetLatestGasCoin ¶
func (ch *Chain) GetLatestGasCoin() *coin.CoinWithRef
func (*Chain) GetMerkleProof ¶
GetMerkleProof return the merkle proof of the key in the smart contract. Assumes Merkle model is used
func (*Chain) GetMerkleProofRaw ¶
func (ch *Chain) GetMerkleProofRaw(key []byte) *trie.MerkleProof
GetMerkleProofRaw returns Merkle proof of the key in the state
func (*Chain) GetRequestIDsForBlock ¶
GetRequestIDsForBlock returns the list of requestIDs settled in a particular block
func (*Chain) GetRequestReceipt ¶
GetRequestReceipt gets the log records for a particular request, the block index and request index in the block
func (*Chain) GetRequestReceiptsForBlock ¶
func (ch *Chain) GetRequestReceiptsForBlock(blockIndex ...uint32) []*blocklog.RequestReceipt
GetRequestReceiptsForBlock returns all request log records for a particular block
func (*Chain) GetRequestReceiptsForBlockRange ¶
func (ch *Chain) GetRequestReceiptsForBlockRange(fromBlockIndex, toBlockIndex uint32) []*blocklog.RequestReceipt
GetRequestReceiptsForBlockRange returns all request log records for range of blocks, inclusively. Upper bound is 'latest block' is set to 0
func (*Chain) GetRootCommitment ¶
GetRootCommitment returns the root commitment of the latest state index
func (*Chain) HasL2Object ¶
func (*Chain) IsRequestProcessed ¶
IsRequestProcessed checks if the request is booked on the chain as processed
func (*Chain) L2Accounts ¶
L2Accounts returns all accounts on the chain with non-zero balances
func (*Chain) L2Assets ¶
L2Assets return all tokens contained in the on-chain account controlled by the 'agentID'
func (*Chain) L2AssetsAtStateIndex ¶
func (*Chain) L2BaseTokensAtStateIndex ¶
func (*Chain) L2CoinBalance ¶
func (*Chain) L2CommonAccountAssets ¶
func (*Chain) L2CommonAccountBaseTokens ¶
func (*Chain) L2CommonAccountNativeTokens ¶
func (*Chain) L2LedgerString ¶
func (*Chain) L2TotalAssets ¶
L2TotalAssets return total sum of ftokens contained in the on-chain accounts
func (*Chain) L2TotalBaseTokens ¶
L2TotalBaseTokens return total sum of base tokens in L2 (all accounts)
func (*Chain) LastReceipt ¶
LastReceipt returns the receipt for the latest request processed by the chain, will return nil if the last block is empty
func (*Chain) LatestBlock ¶
func (*Chain) LatestBlockIndex ¶
func (*Chain) MustDepositBaseTokensToL2 ¶
func (*Chain) NewEthereumAccountWithL2Funds ¶
func (*Chain) PostEthereumTransaction ¶
func (ch *Chain) PostEthereumTransaction(tx *types.Transaction) (isc.CallArguments, error)
func (*Chain) PostRequestOffLedger ¶
func (ch *Chain) PostRequestOffLedger(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, error)
func (*Chain) PostRequestSync ¶
func (ch *Chain) PostRequestSync(req *CallParams, keyPair *cryptolib.KeyPair) (isc.CallArguments, error)
PostRequestSync posts a request synchronously sent by the test program to the smart contract on the same or another chain.
Note that in a real network of Wasp nodes, posting a transaction is completely asynchronous, i.e. result of the call is not available to the originator of the post. Instead, the Solo environment makes PostRequestSync a synchronous call, making it possible to step-by-step debug the smart contract logic.
func (*Chain) PostRequestSyncExt ¶
func (ch *Chain) PostRequestSyncExt( callParams *CallParams, keyPair *cryptolib.KeyPair, ) ( req isc.OnLedgerRequest, l1Res *iotajsonrpc.IotaTransactionBlockResponse, vmRes *vm.RequestResult, anchorTransitionPTBRes *iotajsonrpc.IotaTransactionBlockResponse, err error, )
func (*Chain) PostRequestSyncTx ¶
func (ch *Chain) PostRequestSyncTx(req *CallParams, keyPair *cryptolib.KeyPair) ( onLedregReq isc.OnLedgerRequest, l1Res *iotajsonrpc.IotaTransactionBlockResponse, vmRes *vm.RequestResult, anchorTransitionPTBRes *iotajsonrpc.IotaTransactionBlockResponse, err error, )
func (*Chain) Processors ¶
func (ch *Chain) Processors() *processors.Config
func (*Chain) ResolveVMError ¶
func (ch *Chain) ResolveVMError(e *isc.UnresolvedVMError) *isc.VMError
func (*Chain) RunAllReceivedRequests ¶
func (*Chain) RunOffLedgerRequest ¶
func (ch *Chain) RunOffLedgerRequest(r isc.Request) ( *iotajsonrpc.IotaTransactionBlockResponse, isc.CallArguments, error, )
func (*Chain) RunOffLedgerRequests ¶
func (ch *Chain) RunOffLedgerRequests(reqs []isc.Request) ( *iotajsonrpc.IotaTransactionBlockResponse, []*vm.RequestResult, )
func (*Chain) RunRequestBatch ¶
func (ch *Chain) RunRequestBatch(maxRequestsInBlock int) ( *iotajsonrpc.IotaTransactionBlockResponse, []*vm.RequestResult, )
RunRequestBatch runs a batch of requests pending to be processed
func (*Chain) RunRequestsSync ¶
func (ch *Chain) RunRequestsSync(reqs []isc.Request) ( *iotajsonrpc.IotaTransactionBlockResponse, []*vm.RequestResult, )
func (*Chain) SendFromL1ToL2Account ¶
func (ch *Chain) SendFromL1ToL2Account(toSend isc.CoinBalances, extraDeposit coin.Value, target isc.AgentID, user *cryptolib.KeyPair) error
SendFromL1ToL2Account sends ftokens from L1 address to the target account on L2 Sender pays the gas fee
func (*Chain) SendFromL1ToL2AccountBaseTokens ¶
func (*Chain) SendFromL2ToL2Account ¶
func (ch *Chain) SendFromL2ToL2Account(transfer *isc.Assets, target isc.AgentID, user *cryptolib.KeyPair) error
SendFromL2ToL2Account moves ftokens on L2 from user's account to the target
func (*Chain) SendFromL2ToL2AccountBaseTokens ¶
func (*Chain) SendFromL2ToL2AccountNativeTokens ¶
func (*Chain) SendRequest ¶
func (ch *Chain) SendRequest(req *CallParams, keyPair *cryptolib.KeyPair) (isc.OnLedgerRequest, *iotajsonrpc.IotaTransactionBlockResponse, error)
SendRequest creates a request based on parameters and sigScheme, then send it to the anchor.
func (*Chain) SendRequestWithL1GasBudget ¶
func (ch *Chain) SendRequestWithL1GasBudget( req *CallParams, keyPair *cryptolib.KeyPair, l1GasBudget uint64, ) ( isc.OnLedgerRequest, *iotajsonrpc.IotaTransactionBlockResponse, error, )
func (*Chain) SetGasFeePolicy ¶
func (*Chain) Store ¶
func (ch *Chain) Store() indexedstore.IndexedStore
func (*Chain) TransferAllowanceTo ¶
func (ch *Chain) TransferAllowanceTo( allowance *isc.Assets, targetAccount isc.AgentID, wallet *cryptolib.KeyPair, ) error
TransferAllowanceTo sends an on-ledger request to transfer funds to target account (sends extra base tokens to the sender account to cover gas)
type ChainSnapshot ¶
type InitOptions ¶
type InitOptions struct {
L1Config *L1Config
Debug bool
PrintStackTrace bool
GasBurnLogEnabled bool
Log log.Logger
}
func DefaultInitOptions ¶
func DefaultInitOptions() *InitOptions
type L1L2CoinBalances ¶
type L1L2CoinBalances struct {
Address *cryptolib.Address
L1 isc.CoinBalances
L2 isc.CoinBalances
}
func (*L1L2CoinBalances) String ¶
func (a *L1L2CoinBalances) String() string
type Snapshot ¶
type Snapshot struct {
// UtxoDB *utxodb.UtxoDBState
Chains []*ChainSnapshot
}
type Solo ¶
type Solo struct {
// instance of the test
T Context
// contains filtered or unexported fields
}
Solo is a structure which contains global parameters of the test: one per test instance
func New ¶
func New(t Context, initOptions ...*InitOptions) *Solo
New creates an instance of the Solo environment If solo is used for unit testing, 't' should be the *testing.T instance; otherwise it can be either nil or an instance created with NewTestContext.
func (*Solo) AdvanceClockBy ¶
AdvanceClockBy advances logical clock by time step
func (*Solo) AssertL1BaseTokens ¶
func (*Solo) AssertL1Coins ¶
func (*Solo) GetChainByName ¶
func (*Solo) GetFundsFromFaucet ¶
func (*Solo) GlobalTime ¶
GlobalTime return current logical clock time on the 'solo' instance
func (*Solo) ISCMoveClient ¶
func (env *Solo) ISCMoveClient() *iscmoveclient.Client
func (*Solo) ISCPackageID ¶
func (*Solo) IotaFaucetURL ¶
func (*Solo) IterateChainLatestStates ¶
func (*Solo) IterateChainTrieDBs ¶
func (*Solo) L1AllCoins ¶
func (env *Solo) L1AllCoins(addr *cryptolib.Address) iotajsonrpc.Coins
func (*Solo) L1BaseTokenCoins ¶
func (env *Solo) L1BaseTokenCoins(addr *cryptolib.Address) []*iotajsonrpc.Coin
func (*Solo) L1CoinBalance ¶
func (*Solo) L1CoinBalances ¶
func (env *Solo) L1CoinBalances(addr *cryptolib.Address) isc.CoinBalances
L1CoinBalances returns all ftokens of the address contained in the UTXODB ledger
func (*Solo) L1CoinInfo ¶
func (env *Solo) L1CoinInfo(coinType coin.Type) *parameters.IotaCoinInfo
func (*Solo) L1DeployCoinPackage ¶
func (*Solo) L1MintCoin ¶
func (*Solo) L1MintObject ¶
func (env *Solo) L1MintObject(owner *cryptolib.KeyPair) isc.IotaObject
func (*Solo) L1Params ¶
func (env *Solo) L1Params() *parameters.L1Params
func (*Solo) LoadSnapshot ¶
LoadSnapshot loads a snapshot previously saved with SaveSnapshot
func (*Solo) MustWithWaitForNextVersion ¶
func (env *Solo) MustWithWaitForNextVersion(currentRef *iotago.ObjectRef, cb func()) *iotago.ObjectRef
MustWithWaitForNextVersion waits for an object to change its version and panics on timeouts This tries to make sure that an object meant to be used multiple times, does not get referenced twice with the same ref. Handle with care. Only use it on objects that are expected to be used again, like a GasCoin/Generic coin/Requests
func (*Solo) NewChainExt ¶
func (env *Solo) NewChainExt( chainOriginator *cryptolib.KeyPair, initCommonAccountBaseTokens coin.Value, name string, evmChainID uint16, blockKeepAmount int32, ) (*Chain, *isc.StateAnchor)
NewChainExt returns also origin and init transactions. Used for core testing
If 'chainOriginator' is nil, new one is generated and utxodb.FundsFromFaucetAmount (many) base tokens are loaded from the UTXODB faucet. ValidatorFeeTarget will be set to OriginatorAgentID, and can be changed after initialization. To deploy a chain instance the following steps are performed:
- chain signature scheme (private key), chain address and chain ID are created
- empty virtual state is initialized
- origin transaction is created by the originator and added to the UTXODB
- 'init' request transaction to the 'root' contract is created and added to UTXODB
- backlog processing threads (goroutines) are started
- VM processor cache is initialized
- 'init' request is run by the VM. The 'root' contracts deploys the rest of the core contracts:
Upon return, the chain is fully functional to process requests
func (*Solo) NewKeyPair ¶
func (*Solo) NewKeyPairFromIndex ¶
func (*Solo) NewKeyPairWithFunds ¶
func (env *Solo) NewKeyPairWithFunds(seed ...*cryptolib.Seed) (*cryptolib.KeyPair, *cryptolib.Address)
NewKeyPairWithFunds generates new ed25519 signature scheme and requests some tokens from the UTXODB faucet. The amount of tokens is equal to utxodb.FundsFromFaucetAmount (=1000Mi) base tokens Returns signature scheme interface and public key in binary form
func (*Solo) NewSeedFromTestNameAndTimestamp ¶
func (*Solo) RestoreSnapshot ¶
RestoreSnapshot restores the Solo environment from the given snapshot
func (*Solo) SaveSnapshot ¶
SaveSnapshot saves the given snapshot to a file
func (*Solo) SelectCoinsForGas ¶
func (*Solo) TakeSnapshot ¶
TakeSnapshot generates a snapshot of the Solo environment
func (*Solo) WaitForNewBalance ¶
func (*Solo) WithWaitForNextVersion ¶
func (env *Solo) WithWaitForNextVersion(currentRef *iotago.ObjectRef, cb func()) (*iotago.ObjectRef, error)
WithWaitForNextVersion waits for an object to change its version. This tries to make sure that an object meant to be used multiple times, does not get referenced twice with the same ref. Handle with care. Only use it on objects that are expected to be used again, like a GasCoin/Generic coin/Requests