-
Notifications
You must be signed in to change notification settings - Fork 145
/
sandbox_interface.go
246 lines (215 loc) · 9.08 KB
/
sandbox_interface.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// Copyright 2020 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
package isc
import (
"math/big"
"time"
"github.com/ethereum/go-ethereum/eth/tracers"
iotago "github.com/iotaledger/iota.go/v3"
"github.com/iotaledger/wasp/packages/hashing"
"github.com/iotaledger/wasp/packages/kv"
"github.com/iotaledger/wasp/packages/kv/dict"
"github.com/iotaledger/wasp/packages/vm/gas"
)
// SandboxBase is the common interface of Sandbox and SandboxView
type SandboxBase interface {
Helpers
Balance
// Params returns the parameters of the current call
Params() *Params
// ChainID returns the chain ID
ChainID() ChainID
// ChainOwnerID returns the AgentID of the current owner of the chain
ChainOwnerID() AgentID
// ChainInfo returns information and configuration parameters of the chain
ChainInfo() *ChainInfo
// Contract returns the Hname of the current contract in the context
Contract() Hname
// AccountID returns the agentID of the current contract (i.e. chainID + contract hname)
AccountID() AgentID
// Caller is the agentID of the caller.
Caller() AgentID
// Timestamp returns the Unix timestamp of the current state in seconds
Timestamp() time.Time
// Log returns a logger that outputs on the local machine. It includes Panicf method
Log() LogInterface
// Utils provides access to common necessary functionality
Utils() Utils
// Gas returns sub-interface for gas related functions. It is stateful but does not modify chain's state
Gas() Gas
// GetNFTData returns information about a NFTID (issuer and metadata)
GetNFTData(nftID iotago.NFTID) *NFT
// CallView calls another contract. Only calls view entry points
CallView(contractHname Hname, entryPoint Hname, params dict.Dict) dict.Dict
// StateR returns the immutable k/v store of the current call (in the context of the smart contract)
StateR() kv.KVStoreReader
// SchemaVersion returns the schema version of the current state
SchemaVersion() SchemaVersion
}
type SchemaVersion uint32
type Params struct {
Dict dict.Dict
KVDecoder
}
type Helpers interface {
Requiref(cond bool, format string, args ...interface{})
RequireNoError(err error, str ...string)
}
type Authorize interface {
RequireCaller(agentID AgentID)
RequireCallerAnyOf(agentID []AgentID)
RequireCallerIsChainOwner()
}
type Balance interface {
// BalanceBaseTokens returns number of base tokens in the balance of the smart contract
BalanceBaseTokens() uint64
// BalanceNativeToken returns number of native token or nil if it is empty
BalanceNativeToken(iotago.NativeTokenID) *big.Int
// BalanceNativeTokens returns all native tokens owned by the smart contract
BalanceNativeTokens() iotago.NativeTokens
// OwnedNFTs returns the NFTIDs of NFTs owned by the smart contract
OwnedNFTs() []iotago.NFTID
// returns whether a given user owns a given amount of tokens
HasInAccount(AgentID, *Assets) bool
}
// Sandbox is an interface given to the processor to access the VMContext
// and virtual state, transaction builder and request parameters through it.
type Sandbox interface {
SandboxBase
Authorize
// State k/v store of the current call (in the context of the smart contract)
State() kv.KVStore
// Request return the request in the context of which the smart contract is called
Request() Calldata
// Call calls the entry point of the contract with parameters and allowance.
// If the entry point is full entry point, allowance tokens are available to be moved from the caller's
// accounts (if enough). If the entry point is view, 'allowance' has no effect
Call(target, entryPoint Hname, params dict.Dict, allowance *Assets) dict.Dict
// DeployContract deploys contract on the same chain. 'initParams' are passed to the 'init' entry point
DeployContract(programHash hashing.HashValue, name string, initParams dict.Dict)
// Event emits an event
Event(topic string, payload []byte)
// RegisterError registers an error
RegisterError(messageFormat string) *VMErrorTemplate
// GetEntropy 32 random bytes based on the hash of the current state transaction
GetEntropy() hashing.HashValue
// AllowanceAvailable specifies max remaining (after transfers) budget of assets the smart contract can take
// from the caller with TransferAllowedFunds. Nil means no allowance left (zero budget)
AllowanceAvailable() *Assets
// TransferAllowedFunds moves assets from the caller's account to specified account within the budget set by Allowance.
// Skipping 'assets' means transfer all Allowance().
// The TransferAllowedFunds call mutates AllowanceAvailable
// Returns remaining budget
TransferAllowedFunds(target AgentID, transfer ...*Assets) *Assets
// Send sends an on-ledger request (or a regular transaction to any L1 Address)
Send(metadata RequestParameters)
// EstimateRequiredStorageDeposit returns the amount of base tokens needed to cover for a given request's storage deposit
EstimateRequiredStorageDeposit(r RequestParameters) uint64
// StateAnchor properties of the anchor output
StateAnchor() *StateAnchor
RequestIndex() uint16
// EVMTracer returns a non-nil tracer if an EVM tx is being traced
// (e.g. with the debug_traceTransaction JSONRPC method).
EVMTracer() *EVMTracer
// TakeStateSnapshot takes a snapshot of the state. This is useful to implement the try/catch
// behavior in Solidity, where the state is reverted after a low level call fails.
TakeStateSnapshot() int
RevertToStateSnapshot(int)
// Privileged is a sub-interface of the sandbox which should not be called by VM plugins
Privileged() Privileged
}
// Privileged is a sub-interface for core contracts. Should not be called by VM plugins
type Privileged interface {
TryLoadContract(programHash hashing.HashValue) error
CreateNewFoundry(scheme iotago.TokenScheme, metadata []byte) (uint32, uint64)
DestroyFoundry(uint32) uint64
ModifyFoundrySupply(serNum uint32, delta *big.Int) int64
MintNFT(addr iotago.Address, immutableMetadata []byte, issuer iotago.Address) (uint16, *iotago.NFTOutput)
GasBurnEnable(enable bool)
GasBurnEnabled() bool
RetryUnprocessable(req Request, outputID iotago.OutputID)
OnWriteReceipt(CoreCallbackFunc)
CallOnBehalfOf(caller AgentID, target, entryPoint Hname, params dict.Dict, allowance *Assets) dict.Dict
SendOnBehalfOf(caller ContractIdentity, metadata RequestParameters)
// only called from EVM
MustMoveBetweenAccounts(fromAgentID, toAgentID AgentID, assets *Assets)
DebitFromAccount(AgentID, *big.Int)
CreditToAccount(AgentID, *big.Int)
}
type CoreCallbackFunc func(contractPartition kv.KVStore, gasBurned uint64)
// RequestParameters represents parameters of the on-ledger request. The output is build from these parameters
type RequestParameters struct {
// TargetAddress is the target address. It may represent another chain or L1 address
TargetAddress iotago.Address
// Assets attached to the output, always taken from the caller's account.
// It expected to contain base tokens at least the amount required for storage deposit
// It depends on the context how it is handled when base tokens are not enough for storage deposit
Assets *Assets
// AdjustToMinimumStorageDeposit if true base tokens in attached fungible tokens will be added to meet minimum storage deposit requirements
AdjustToMinimumStorageDeposit bool
// Metadata is a request metadata. It may be nil if the output is just sending assets to L1 address
Metadata *SendMetadata
// SendOptions includes options of the output, such as time lock or expiry parameters
Options SendOptions
}
type Gas interface {
Burn(burnCode gas.BurnCode, par ...uint64)
Budget() uint64
Burned() uint64
EstimateGasMode() bool
}
// StateAnchor contains properties of the anchor output/transaction in the current context
type StateAnchor struct {
ChainID ChainID
Sender iotago.Address
OutputID iotago.OutputID
IsOrigin bool
StateController iotago.Address
GovernanceController iotago.Address
StateIndex uint32
StateData []byte
Deposit uint64
NativeTokens iotago.NativeTokens
}
type SendOptions struct {
Timelock time.Time
Expiration *Expiration
}
type Expiration struct {
Time time.Time
ReturnAddress iotago.Address
}
// SendMetadata represents content of the data payload of the output
type SendMetadata struct {
TargetContract Hname
EntryPoint Hname
Params dict.Dict
Allowance *Assets
GasBudget uint64
}
// Utils implement various utilities which are faster on host side than on wasm VM
// Implement deterministic stateless computations
type Utils interface {
Hashing() Hashing
ED25519() ED25519
BLS() BLS
}
type Hashing interface {
Blake2b(data []byte) hashing.HashValue
Hname(name string) Hname
Keccak(data []byte) hashing.HashValue
Sha3(data []byte) hashing.HashValue
}
type ED25519 interface {
ValidSignature(data []byte, pubKey []byte, signature []byte) bool
AddressFromPublicKey(pubKey []byte) (iotago.Address, error)
}
type BLS interface {
ValidSignature(data []byte, pubKey []byte, signature []byte) bool
AddressFromPublicKey(pubKey []byte) (iotago.Address, error)
AggregateBLSSignatures(pubKeysBin [][]byte, sigsBin [][]byte) ([]byte, []byte, error)
}
type EVMTracer struct {
Tracer tracers.Tracer
TxIndex uint64
}