Documentation ¶
Index ¶
- Constants
- Variables
- func EVMMaybeUnmarshalEncryptedData(data []byte, result *[]byte) (*encryption.EncryptedData, *sdkTypes.FailedCallResult, error)
- func InterfaceID(abi *abi.ABI) []byte
- type ERC721AssetMetadata
- type EVMContractData
- type EVMDeterministicError
- type EVMNFTData
- type EVMPossibleToken
- type EVMTokenBalanceData
- type EVMTokenData
- type EVMTokenMutableData
Constants ¶
const ERC165GasLimit uint64 = 30_000
const MaxMetadataBytes = 10 * 1024 * 1024
const NativeRuntimeTokenAddress = "oasis1runt1menat1vet0ken0000000000000000000000"
A fake address that is used to represent the native runtime token in contexts that are primarily intended for tracking EVM tokens (= contract-based tokens).
Variables ¶
var ( // https://github.com/oasisprotocol/oasis-web3-gateway/blob/v3.0.0/rpc/eth/api.go#L403-L408 DefaultGasPrice = []byte{1} DefaultGasLimit uint64 = 30_000_000 DefaultCaller = ethCommon.Address{1}.Bytes() DefaultValue = []byte{0} )
var ( InvalidInterfaceID = []byte{0xff, 0xff, 0xff, 0xff} ERC165InterfaceID = InterfaceID(evmabi.ERC165) ERC721InterfaceID = InterfaceID(evmabi.ERC721) ERC721TokenReceiverInterfaceID = InterfaceID(evmabi.ERC721TokenReceiver) ERC721MetadataInterfaceID = InterfaceID(evmabi.ERC721Metadata) ERC721EnumerableInterfaceID = InterfaceID(evmabi.ERC721Enumerable) )
Functions ¶
func EVMMaybeUnmarshalEncryptedData ¶
func EVMMaybeUnmarshalEncryptedData(data []byte, result *[]byte) (*encryption.EncryptedData, *sdkTypes.FailedCallResult, error)
EVMMaybeUnmarshalEncryptedData breaks down a possibly encrypted data + result into their encryption envelope fields. If the data is not encrypted, it returns nil with no error. This may uncover an encapsulated failed result in certain old Sapphire-style encrypted transactions, which it will return.
LESSON: Oasis paratime transaction structure.
Oasis paratime transactions conform to the oasis format transaction payload: https://github.com/oasisprotocol/oasis-sdk/blob/04e8918a9b3eb90caffe115ea2d46b5742438714/client-sdk/go/types/transaction.go#L212
Transaction payloads may be encrypted in oasis. To express that, the Transaction.Call field of the transaction would have a call format set, e.g.
Call.Format: 'encrypted/x25519-deoxysii'
This gives rise to the concept of outer/inner calls for oasis-format transactions, where the inner call would be encrypted and stored in the outer Call.Body. However, when the runtime evm module converts ethereum format transactions to oasis format transaction payloads, they are never in this encrypted mode because there is no native ethereum way to express an encrypted transaction.
Thus, for ethereum format transactions, the outer oasis format Call.Format is always 0/plain (or equivalently, unset). This outer Call directly has the method and body of the transaction. For example, the method may be "evm.Call" and the body would be the corresponding struct: https://github.com/oasisprotocol/oasis-sdk/blob/04e8918a9b3eb90caffe115ea2d46b5742438714/client-sdk/go/modules/evm/types.go#L13
Here is where we may encounter sapphire-style encryption. In the first and most basic case, there is no sapphire-style encryption at all and the fields of the evm.Call struct are the exact bytes that would go into the evm. Note that Sapphire supports this mode.
The result of this transaction is stored in the associated CallResult struct that is returned alongside the transaction in TransactionWithResult: https://github.com/oasisprotocol/oasis-sdk/blob/main/client-sdk/go/client/client.go#L146
A transaction may also be in sapphire encrypted mode. In this case, the evm.Call.Data or evm.Create.Initcode field is itself a cbor-encoded oasis format runtime-sdk Call struct that we term the "sapphire outer call". This struct is the same oasis format Transaction.Call mentioned above: https://github.com/oasisprotocol/oasis-sdk/blob/04e8918a9b3eb90caffe115ea2d46b5742438714/client-sdk/go/types/transaction.go#L363
In encrypted mode, the sapphire outer call has a Call.Format of 'encrypted/x25519-deoxysii', and the call.Body is a cbor-encoded encryption envelope, which can be decrypted and parsed into another oasis format Call struct that we term the "sapphire inner call". Note that Nexus never has the keys the decrypt this envelope to get the inner struct since the Sapphire transaction is encrypted. The sapphire inner call.Body has the evm input data, and the inner call.Format is always unset.
The results of sapphire encrypted transactions are stored similarly. In the first case, we should note that sapphire encrypted transactions may have unencrypted results if the inputs were not encrypted. Unencrypted transaction results are stored in the same associated CallResult as the results of unencrypted transactions. We term this CallResult the "outer call result."
Encrypted results can be recovered by cbor-unmarshalling the outer CallResult.Ok field into another CallResult struct that we term the "sapphire outer call result." Currently, the sapphire outer CallResult.Ok stores the result envelope of successful sapphire encrypted transactions. However, in older versions of Sapphire and for non-evm transactions, this result envelope is stored in the sapphire outer CallResult.Unknown.
The result envelope contains the encrypted "sapphire inner call result", where the sapphire inner CallResult.Ok field contains the output data from the evm. Note that Nexus does not have the keys to decrypt and access this sapphire inner call result.
Side note: The CallResult struct does not specify its own encryption format. Rather, it follows the format of its corresponding oasis format Call. The "outer call" Call.Format corresponds to the outer call result, and the "sapphire outer call" Call.Format corresponds to the sapphire outer call result.
Currently, if an encrypted transaction fails, the error is bubbled up to the outer CallResult.Failed. However, in older versions of Sapphire the error was stored in the sapphire outer CallResult.Failed.
Lastly, there's also a "not-encryption-but-sapphire-something" case where the sapphire outer Call.Format is set to "plain". In this case, there's no sapphire inner call and the sapphire outer Call.Body has the evm input data. Nexus does not extract the evm input data directly here like the way it does for unencrypted evm.Call transactions.
The results of these "plain" transactions are returned in the outer CallResult.
Outer oasis Call.Body
-> inner oasis Call -> evm.Call -> sapphire outer Call.Body -> sapphire inner Call
To summarize: * Non-Sapphire
- Tx Body: Stored in oasis outer Call.Body
- Success Result: Stored in outer oasis CallResult.Ok
- Failure Result: Stored in outer oasis CallResult.Failed
* Sapphire Encrypted
- Tx Body: Encryption envelope stored in sapphire outer Call.Body
- Success Result: Encryption envelope stored in either sapphire outer CallResult.Ok (new) or CallResult.Unknown (old)
- Failure Result: Stored in either the sapphire outer CallResult.Failed (old) or the outer oasis CallResult.Failed (new)
* Sapphire Plain(0)
- Tx Body: Stored in the sapphire outer Call.Body
- Success Result: Stored in outer oasis CallResult.Ok
- Failure Result: Stored in outer oasis CallResult.Failed
func InterfaceID ¶
Types ¶
type ERC721AssetMetadata ¶ added in v0.1.16
type ERC721AssetMetadata struct { // Name identifies the asset which this NFT represents Name *string `json:"name"` // Description describes the asset which this NFT represents Description *string `json:"description"` // Image is A URI pointing to a resource with mime type image/* // representing the asset which this NFT represents. (Additional // non-descriptive text from ERC-721 omitted.) Image *string `json:"image"` }
ERC721AssetMetadata is asset metadata https://eips.ethereum.org/EIPS/eip-721
type EVMContractData ¶
type EVMDeterministicError ¶
type EVMDeterministicError struct {
// contains filtered or unexported fields
}
func (EVMDeterministicError) Is ¶
func (err EVMDeterministicError) Is(target error) bool
type EVMNFTData ¶ added in v0.1.16
type EVMNFTData struct { MetadataURI *string MetadataAccessed *time.Time Metadata *string Name *string Description *string Image *string }
func EVMDownloadNewNFT ¶ added in v0.1.16
type EVMPossibleToken ¶
type EVMPossibleToken struct { // True if a mutable property of the token (e.g. total_supply) has changed and this // module wants to indicate that the contract should be queried to get the new value // of the mutable property (or ideally just verify it if we'll also dead-reckon it). Mutated bool TotalSupplyChange big.Int NumTransfersChange uint64 }
A contract that "looks like" a token contract, e.g. because it emitted a Transfer event.
type EVMTokenBalanceData ¶
type EVMTokenBalanceData struct { // Balance... if you're here to ask about why there's a "balance" struct // with a Balance field, it's because the struct is really a little // document that the EVMDownloadTokenBalance function can optionally give // you about an account. (And we didn't name the struct "account" because // the only thing inside it is the balance.) We let that function return a // *EVMTokenBalanceData so that it can return nil if it can determine that // the contract is not supported. Plus, Go's idea of an arbitrary size // integer is *big.Int, and we don't want anyone fainting if they see a // ** in the codebase. Balance *big.Int }
func EVMDownloadTokenBalance ¶
func EVMDownloadTokenBalance(ctx context.Context, logger *log.Logger, source nodeapi.RuntimeApiLite, round uint64, tokenEthAddr []byte, accountEthAddr []byte, tokenType common.TokenType) (*EVMTokenBalanceData, error)
EVMDownloadTokenBalance tries to download the balance of a given account for a given token. If it transiently fails to download the balance, it returns with a non-nil error. If it deterministically cannot download the balance, it returns nil with nil error as well. Note that this latter case is not considered an error!
type EVMTokenData ¶
type EVMTokenData struct { Type common.TokenType Name string Symbol string Decimals uint8 *EVMTokenMutableData }
func EVMDownloadNewToken ¶
func EVMDownloadNewToken(ctx context.Context, logger *log.Logger, source nodeapi.RuntimeApiLite, round uint64, tokenEthAddr []byte) (*EVMTokenData, error)
EVMDownloadNewToken tries to download the data of a given token. If it transiently fails to download the data, it returns with a non-nil error. If it deterministically cannot download the data, it returns a struct with the `Type` field set to `TokenTypeUnsupported`.
type EVMTokenMutableData ¶
func EVMDownloadMutatedToken ¶
func EVMDownloadMutatedToken(ctx context.Context, logger *log.Logger, source nodeapi.RuntimeApiLite, round uint64, tokenEthAddr []byte, tokenType common.TokenType) (*EVMTokenMutableData, error)
EVMDownloadMutatedToken tries to download the mutable data of a given token. If it transiently fails to download the data, it returns with a non-nil error. If it deterministically cannot download the data, it returns nil with nil error as well. Note that this latter case is not considered an error!