Class Context
Execution context includes: - The current on-Chain state, including the defined execution environment for each Address - Local lexical bindings for the current execution position - The identity (as an Address) for the origin, caller and currently executing actor - Juice and execution depth current status for - Result of the last operation executed (which may be exceptional)
Interestingly, this behaves like Scala's ZIO[Context-Stuff, AExceptional, T]
Contexts maintain checks on execution depth and juice to control against arbitrary on-chain execution. Coupled with limits on total juice and limits on memory allocation per unit juice, this places an upper bound on execution time and space.
Contexts also support returning exceptional values. Exceptional results may come from arbitrary nested depth (which requires a bit of complexity to reset depth when catching exceptional values). We avoid using Java exceptions here, because exceptionals are "normal" in the context of on-chain execution, and we'd like to avoid the overhead of exception handling - may be especially important in DoS scenarios.
"If you have a procedure with 10 parameters, you probably missed some" - Alan Perlis
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static final class
Inner class for less-frequently changing CVM state related to Actor execution Should save some allocation / GC on average, since it will change less frequently than the surrounding Context and can be cheaply copied by reference.static final class
Inner class compiler state. -
Field Summary
Fields -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotected
Context
(Context.ChainState chainState, long juice, long juiceLimit, AVector<ACell> localBindings2, ACell result, int depth, AExceptional exception, AVector<AVector<ACell>> log, Context.CompilerState comp) -
Method Summary
Modifier and TypeMethodDescriptionacceptFunds
(long amount) Accepts offered funds for the given address.Executes a call to an Actor.Executes a call to an Actor.Appends a log entry for the current address.boolean
checkJuice
(long gulp) Checks if there is sufficient juice for a given gulp of consumption.Compile a form in this Context.compileAll
(ASequence<ACell> forms) Compiles a sequence of forms in the current context.completeTransaction
(State initialState, ResultContext rc) Performs key actions at the end of a transaction: Refunds juice Accumulates used juice fees in globals Increments sequence numberconsumeJuice
(long gulp) Consumes juice, returning an updated context if sufficient juice remains or an exceptional JUICE error.static Context
createFake
(State state) Creates an execution context with a default actor address.static Context
createFake
(State state, Address origin) Creates a "fake" execution context for the given address.static Context
createInitial
(State state, Address origin, long juiceLimit) Creates an initial execution context with the specified actor as origin, and reserving the appropriate amount of juice.createPeer
(AccountKey accountKey, long initialStake) Creates a new peer with the specified stake.Defines a value in the environment of the current addressdefineWithSyntax
(Syntax syn, ACell value) Defines a value in the environment of the current address, updating the metadataDeploys a new account.Executes a form in the current context.Evaluates a form as another Address.Executes an op as a top level instruction (no local bindings)Executes an Op within this context, returning an updated context.executeLocalBinding
(ACell bindingForm, AOp<?> op) Execute an op, and bind the result to the given binding form in the lexical environment Binding form may be a destructuring formExpands a form with the default *initial-expander*expandCompile
(ACell form) Expand and compile a form in this Context.fork()
Forks this context, creating a new copy of all local state but clears any exceptional valueforkWithAddress
(Address newAddress) Switches the context to a new address, creating a new execution context.Gets the account status for the current AddressgetAccountStatus
(Address address) Gets the account status record, or null if not foundGets the address of the currently executing Account.long
Gets the balance for the current Addresslong
getBalance
(Address address) Gets the balance for the specified AddressGets the caller of the currently executing context.Gets the compiler stateint
getDepth()
Gets the current EnvironmentgetError()
Gets the Error from this Context, or null if not an ErrorGets the error code of this context's return valueGets the exceptional value from this context.Gets the holdings map for the current account.long
Get the juice available in this Contextlong
Get the juice limit in this Contextlong
Get the juice used so far in this ContextgetLog()
Gets the log map for the current context.Gets the metadata for the current Accountlong
getOffer()
Get the current offer from this Context<R extends ACell>
RGets the result from this context.getScope()
Gets the scope of the currently executing context.getState()
Get the latest state from this ContextGets the current timestamp for this context.getValue()
Gets the resulting value from this context.handleStateResults
(Context returnContext, boolean rollback) Handle results at the end of an execution boundary (actor call, transaction etc.)Invokes a function within this context, returning an updated context.boolean
isError()
Tests if this Context's current status contains an Error.boolean
Tests if this Context holds an exceptional result.boolean
isValidAccount
(Address address) Tests if an Address is valid, i.e.Looks up a symbol's value in the current execution context, without any effect on the Context (no juice consumed etc.)lookupDefiningAddress
(Address address, Symbol sym) Looks up the address of the account that defines a given SymbollookupDynamic
(Address address, Symbol symbol) Looks up a value in the dynamic environment.lookupDynamic
(Symbol symbol) Looks up a value in the dynamic environment.lookupDynamicEntry
(Address address, Symbol sym) Looks up an environment entry for a specific address without consuming juice.lookupExpander
(ACell form) Looks up an expander from a form in this contextlookupMeta
(Address address, Symbol sym) Looks up Metadata for the given symbol in this contextlookupMeta
(Symbol sym) Looks up Metadata for the given symbol in this contextlookupValue
(Address address, Symbol sym) Looks up value for the given symbol in this contextlookupValue
(Symbol sym) Looks up value for the given symbol in this context<T extends ACell>
TlookupValue
(String symName) Looks up value for the given symbol in this contextboolean
print
(BlobBuilder bb, long limit) Executes code as if run in the specified account, but always rolling back state changes.Executes a form at the top level.Executes an Op at the top level in a new forked Context.Schedules an operation for the specified future timestamp.setAccountKey
(AccountKey publicKey) Sets the public key for the current accountsetController
(ACell address) Sets the controller for the current AccountsetDelegatedStake
(AccountKey peerKey, long newStake) Sets the delegated stake on a specified peer to the specified level.setHolding
(Address targetAddress, ACell value) Sets the holding for a specified target account.setMemory
(long allowance) Sets the memory allowance for the current account, buying / selling from the pool as necessary to ensure the correct final allowanceSets the parent for the current AccountsetPeerData
(AccountKey peerKey, AHashMap<ACell, ACell> data) Sets peer data.setPeerStake
(AccountKey peerKey, long newStake) Sets the stake for a given Peer, transferring coins from the current address.toString()
Transfers funds from the current address to the target.transferMemoryAllowance
(Address target, CVMLong amountToSend) Transfers memory allowance from the current address to the target.Removes a definition mapping in the environment of the current addressupdateBindings
(ACell bindingForm, Object args) Updates local bindings with a given binding formprotected Context
withAccountStatus
(Address target, AccountStatus accountStatus) withArgumentError
(String message) withArityError
(String message) withAssertError
(String message) withBoundsError
(long index) withCastError
(int argIndex, ACell[] args, AType klass) withCastError
(int argIndex, AType klass) withCastError
(ACell a, AType klass) withCastError
(ACell a, String message) withCastError
(AType klass) withCompileError
(String message) withError
(ErrorValue error) withException
(long gulp, AExceptional value) withException
(AExceptional exception) withFundsError
(String message) withJuice
(long newJuice) Returns this context with a JUICE error, consuming all juice.withJuiceLimit
(long newJuiceLimit) withLocalBindings
(AVector<ACell> newBindings) Updates this Context with new local bindings.withResult
(long gulp, ACell value) withResult
(ACell value) Returns a context updated with the specified result.withSyntaxError
(String message) Updates this context with a given value, which may either be a normal result or exceptional value
-
Field Details
-
EMPTY_BINDINGS
-
-
Constructor Details
-
Context
protected Context(Context.ChainState chainState, long juice, long juiceLimit, AVector<ACell> localBindings2, ACell result, int depth, AExceptional exception, AVector<AVector<ACell>> log, Context.CompilerState comp)
-
-
Method Details
-
createFake
-
createFake
Creates a "fake" execution context for the given address. Not valid for use in real transactions, but can be used to compute stuff off-chain "as-if" the actor made the call.- Parameters:
state
- State to use for this Contextorigin
- Origin address to use- Returns:
- Fake context
-
createInitial
Creates an initial execution context with the specified actor as origin, and reserving the appropriate amount of juice. Juice reserve is extracted from the actor's current balance.- Parameters:
state
- Initial State for Contextorigin
- Origin Address for ContextjuiceLimit
- Initial juice requested for Context- Returns:
- Initial execution context with reserved juice.
-
completeTransaction
Performs key actions at the end of a transaction:- Refunds juice
- Accumulates used juice fees in globals
- Increments sequence number
- Parameters:
initialState
- State before transaction execution (after prepare)rc
- Juice price of current execution- Returns:
- Updated context
-
withState
-
getState
-
getJuiceUsed
public long getJuiceUsed()Get the juice used so far in this Context- Returns:
- Juice used
-
getJuiceAvailable
public long getJuiceAvailable()Get the juice available in this Context- Returns:
- Juice available
-
getJuiceLimit
public long getJuiceLimit()Get the juice limit in this Context- Returns:
- Juice limit
-
getOffer
public long getOffer()Get the current offer from this Context- Returns:
- Offered amount in Convex copper
-
getEnvironment
-
getCompilerState
Gets the compiler state- Returns:
- CompilerState instance
-
getMetadata
-
consumeJuice
Consumes juice, returning an updated context if sufficient juice remains or an exceptional JUICE error.- Parameters:
gulp
- Amount of juice to consume- Returns:
- Updated context with juice consumed
-
checkJuice
public boolean checkJuice(long gulp) Checks if there is sufficient juice for a given gulp of consumption. Does not alter context in any way.- Parameters:
gulp
- Amount of juice to be consumed.- Returns:
- true if juice is sufficient, false otherwise.
-
lookup
-
lookupDynamic
-
lookupDynamic
Looks up a value in the dynamic environment. Consumes no juice. Returns an UNDECLARED exception if the symbol cannot be resolved. Returns a NOBODY exception if the specified Account does not exist- Parameters:
address
- Address of account in which to look up valuesymbol
- Symbol to look up- Returns:
- Updated Context
-
lookupMeta
-
lookupMeta
Looks up Metadata for the given symbol in this context- Parameters:
address
- Address to use for lookup (may pass null for current environment)sym
- Symbol to look up- Returns:
- Metadata for given symbol (may be empty) or null if undeclared
-
lookupDefiningAddress
Looks up the address of the account that defines a given Symbol- Parameters:
address
- Address to look up in first instance (null for current address).sym
- Symbol to look up- Returns:
- Context with result as the address defining the given symbol (or null if undeclared)
-
lookupValue
-
lookupValue
-
lookupValue
-
lookupDynamicEntry
-
getAccountStatus
Gets the account status for the current Address- Returns:
- AccountStatus object, or null if not found
-
getHoldings
-
getBalance
public long getBalance()Gets the balance for the current Address- Returns:
- Balance in Convex Coins
-
getBalance
Gets the balance for the specified Address- Parameters:
address
- Address to check balance for- Returns:
- Balance in Convex Coins
-
getCaller
Gets the caller of the currently executing context. Will be null if this context was not called from elsewhere (e.g. is an origin context)- Returns:
- Caller of the currently executing context
-
getScope
Gets the scope of the currently executing context. Will be null if no scope was set- Returns:
- Caller of the currently executing context
-
getAddress
Gets the address of the currently executing Account. May be the current actor, or the address of the account that executed this transaction if no Actors have been called.- Returns:
- Address of the current account, cannot be null, must be a valid existing account
-
getResult
Gets the result from this context. Throws an Error if the context return value is exceptional.- Returns:
- Result value from this Context.
-
getValue
Gets the resulting value from this context. May be either exceptional or a normal result.- Returns:
- Either the normal result, or an AExceptional instance
-
getExceptional
Gets the exceptional value from this context. Throws an Error is the context return value is normal.- Returns:
- an AExceptional instance
-
withResult
-
withValue
-
withResult
-
withJuiceError
Returns this context with a JUICE error, consuming all juice.- Returns:
- Exceptional Context signalling JUICE error.
-
withException
-
withException
-
execute
-
run
-
run
-
invoke
-
executeLocalBinding
Execute an op, and bind the result to the given binding form in the lexical environment Binding form may be a destructuring form- Parameters:
bindingForm
- Binding formop
- Op to execute to get binding values- Returns:
- Context with local bindings updated
-
updateBindings
-
print
-
toString
-
getLocalBindings
-
withLocalBindings
-
getAccountStatus
Gets the account status record, or null if not found- Parameters:
address
- Address of account- Returns:
- AccountStatus for the specified address, or null if the account does not exist
-
getDepth
public int getDepth() -
getOrigin
-
define
-
defineWithSyntax
Defines a value in the environment of the current address, updating the metadata- Parameters:
syn
- Syntax Object to define, containing a Symbol valuevalue
- Value to set of the given Symbol- Returns:
- Updated context with symbol defined in environment
-
undefine
-
expandCompile
-
compile
-
eval
Executes a form in the current context. Ops are executed directly. Other forms will be expanded and compiled before execution, according to `compile` as defined in the current environment- Parameters:
form
- Form to evaluate- Returns:
- Context containing the result of evaluating the specified form
-
exec
-
evalAs
-
queryAs
Executes code as if run in the specified account, but always rolling back state changes.- Parameters:
address
- Address of Account in which to execute the queryform
- Code to execute.- Returns:
- Context updated with only query result and juice consumed
-
compileAll
-
withJuice
-
withJuiceLimit
-
withCompilerState
-
isExceptional
public boolean isExceptional()Tests if this Context holds an exceptional result. Ops should cancel and return exceptional results unchanged, unless they can handle them.- Returns:
- true if context has an exceptional value, false otherwise
-
isError
public boolean isError()Tests if this Context's current status contains an Error. Errors are an uncatchable subset of Exceptions.- Returns:
- true if context has an Error value, false otherwise
-
isValidAccount
Tests if an Address is valid, i.e. refers to an existing Account- Parameters:
address
- Address to check. May be null- Returns:
- true if Account exists, false otherwise
-
transfer
Transfers funds from the current address to the target. Uses no juice- Parameters:
target
- Target Address, will be created if does not already exist.amount
- Amount to transfer, must be between 0 and Amount.MAX_VALUE inclusive- Returns:
- Context with sent amount if the transaction succeeds, or an exceptional value if the transfer fails
-
transferMemoryAllowance
Transfers memory allowance from the current address to the target. Uses no juice- Parameters:
target
- Target Address, must already existamountToSend
- Amount of memory to transfer, must be between 0 and Amount.MAX_VALUE inclusive- Returns:
- Context with a null result if the transaction succeeds, or an exceptional value if the transfer fails
-
setMemory
Sets the memory allowance for the current account, buying / selling from the pool as necessary to ensure the correct final allowance- Parameters:
allowance
- New memory allowance- Returns:
- Context indicating the price paid for the allowance change (may be zero or negative for refund)
-
acceptFunds
Accepts offered funds for the given address. STATE error if offered amount is insufficient. ARGUMENT error if acceptance is negative.- Parameters:
amount
- Amount to accept- Returns:
- Updated context, with long amount accepted as result
-
actorCall
Executes a call to an Actor. Utility function which convert a java String function name- Parameters:
target
- Target Actor address or scope vectoroffer
- Amount of Convex Coins to offer in Actor callfunctionName
- Symbol of function name defined by Actorargs
- Arguments to Actor function invocation- Returns:
- Context with result of Actor call (may be exceptional)
-
actorCall
Executes a call to an Actor.- Parameters:
target
- Target Actor addressoffer
- Amount of Convex Coins to offer in Actor callfunctionName
- Symbol of function name defined by Actorargs
- Arguments to Actor function invocation- Returns:
- Context with result of Actor call (may be exceptional)
-
handleStateResults
Handle results at the end of an execution boundary (actor call, transaction etc.)- Parameters:
returnContext
- Context containing return from child transaction / callrollback
- If true, always rolls back state effects- Returns:
- Updated parent context
-
deploy
Deploys a new account. Arguments must be an account setup code, which will be evaluated in the new account. Result will contain the new address if successful, an exception otherwise.- Parameters:
code
- Account initialisation code- Returns:
- Updated Context with account deployed, or an exceptional result
-
withError
-
withError
-
withError
-
withError
-
withError
-
withArityError
-
withCompileError
-
withSyntaxError
-
withUndeclaredError
-
withBoundsError
-
withCastError
-
withCastError
-
withCastError
-
withCastError
-
withCastError
-
getErrorCode
Gets the error code of this context's return value- Returns:
- The ErrorType of the current exceptional value, or null if there is no error.
-
getError
Gets the Error from this Context, or null if not an Error- Returns:
- The ErrorType of the current exceptional value, or null if there is no error.
-
withAssertError
-
withFundsError
-
withArgumentError
-
getTimeStamp
Gets the current timestamp for this context. The timestamp is the greatest timestamp of all blocks in consensus (including the currently executing block).- Returns:
- Timestamp in milliseconds since UNIX epoch
-
schedule
-
setDelegatedStake
Sets the delegated stake on a specified peer to the specified level. May set to zero to remove stake. Stake will be capped by current balance.- Parameters:
peerKey
- Peer Account key on which to stakenewStake
- Amount to stake- Returns:
- Context with amount of coins transferred to Peer as result (may be negative if stake withdrawn)
-
setPeerStake
Sets the stake for a given Peer, transferring coins from the current address.- Parameters:
peerKey
- Peer Account Key for which to update StakenewStake
- New stake for Peer- Returns:
- Updated Context
-
createPeer
Creates a new peer with the specified stake. The accountKey must not be in the list of peers. The accountKey must be assigend to the current transaction address Stake must be greater than 0. Stake must be less than to the account balance.- Parameters:
accountKey
- Peer Account key to create the PeerStatusinitialStake
- Initial stake amount- Returns:
- Context with final take set
-
setPeerData
Sets peer data.- Parameters:
peerKey
- Peer to set data fordata
- Map of data to set for the peer- Returns:
- Context with final peer data set
-
setHolding
-
setController
-
setParent
-
setAccountKey
Sets the public key for the current account- Parameters:
publicKey
- New Account Public Key- Returns:
- Context with current Account Key set
-
withAccountStatus
-
forkWithAddress
-
fork
Forks this context, creating a new copy of all local state but clears any exceptional value- Returns:
- A new forked Context
-
appendLog
-
getLog
-
lookupCNS
-
expand
-
expand
-
lookupExpander
-