evm

package
v0.14.1-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 27, 2025 License: GPL-3.0, LGPL-3.0 Imports: 105 Imported by: 29

README

EVM Package

The EVM package implements the AvalancheGo VM interface.

VM

The VM creates the Ethereum backend and provides basic block building, parsing, and retrieval logic to the consensus engine.

APIs

The VM creates APIs for the node through the function CreateHandlers(). CreateHandlers returns the Service struct to serve Coreth specific APIs. Additionally, the Ethereum backend APIs are also returned at the /rpc extension.

Block Handling

The VM implements buildBlock, parseBlock, and getBlock and uses the chain package from AvalancheGo to construct a metered state, which uses these functions to implement an efficient caching layer and maintain the required invariants for blocks that get returned to the consensus engine.

To do this, the VM uses a modified version of the Ethereum RLP block type here and uses the core package's BlockChain type here to handle the insertion and storage of blocks into the chain.

Block

The Block type implements the AvalancheGo ChainVM Block interface. The key functions for this interface are Verify(), Accept(), Reject(), and Status().

The Block type wraps the stateless block type here and implements these functions to allow the consensus engine to verify blocks as valid, perform consensus, and mark them as accepted or rejected. See the documentation in AvalancheGo for the more detailed VM invariants that are maintained here.

Atomic Transactions

Atomic transactions utilize Shared Memory (documented here) to send assets to the P-Chain and X-Chain.

Operations on shared memory cannot be reverted, so atomic transactions must separate their verification and processing into two stages: verifying the transaction as valid to be performed within its block and actually performing the operation. For example, once an export transaction is accepted, there is no way for the C-Chain to take that asset back and it can be imported immediately by the recipient chain.

The C-Chain uses the account model for its own state, but atomic transactions must be compatible with the P-Chain and X-Chain, such that C-Chain atomic transactions must transform between the account model and the UTXO model.

Documentation

Index

Constants

View Source
const (
	GenesisTestAddr = "0x751a0b96e1042bee789452ecb20253fba40dbe85"
	GenesisTestKey  = "0xabd71b35d559563fea757f0f5edbde286fb8c043105b15abb7cd57189306d7d1"
)

test constants

Variables

View Source
var (
	// GitCommit is set by the build script
	GitCommit string
	// Version is the version of Coreth
	Version string = "v0.14.1"
)
View Source
var (
	// ID this VM should be referenced by
	ID = ids.ID{'e', 'v', 'm'}
)

Functions

func NewAtomicTxRepository added in v0.8.3

func NewAtomicTxRepository(
	db *versiondb.Database, codec codec.Manager, lastAcceptedHeight uint64,
) (*atomicTxRepository, error)

Types

type Admin added in v0.7.4

type Admin struct {
	// contains filtered or unexported fields
}

Admin is the API service for admin API calls

func NewAdminService added in v0.7.4

func NewAdminService(vm *VM, performanceDir string) *Admin

func (*Admin) GetVMConfig added in v0.8.9

func (p *Admin) GetVMConfig(_ *http.Request, _ *struct{}, reply *client.ConfigReply) error

func (*Admin) LockProfile added in v0.7.4

func (p *Admin) LockProfile(_ *http.Request, _ *struct{}, _ *api.EmptyReply) error

LockProfile runs a mutex profile writing to the specified file

func (*Admin) MemoryProfile added in v0.7.4

func (p *Admin) MemoryProfile(_ *http.Request, _ *struct{}, _ *api.EmptyReply) error

MemoryProfile runs a memory profile writing to the specified file

func (*Admin) SetLogLevel added in v0.7.4

func (p *Admin) SetLogLevel(_ *http.Request, args *client.SetLogLevelArgs, reply *api.EmptyReply) error

func (*Admin) StartCPUProfiler added in v0.7.4

func (p *Admin) StartCPUProfiler(_ *http.Request, _ *struct{}, _ *api.EmptyReply) error

StartCPUProfiler starts a cpu profile writing to the specified file

func (*Admin) StopCPUProfiler added in v0.7.4

func (p *Admin) StopCPUProfiler(r *http.Request, _ *struct{}, _ *api.EmptyReply) error

StopCPUProfiler stops the cpu profile

type AtomicBackend added in v0.9.0

type AtomicBackend interface {
	// InsertTxs calculates the root of the atomic trie that would
	// result from applying [txs] to the atomic trie, starting at the state
	// corresponding to previously verified block [parentHash].
	// If [blockHash] is provided, the modified atomic trie is pinned in memory
	// and it's the caller's responsibility to call either Accept or Reject on
	// the AtomicState which can be retreived from GetVerifiedAtomicState to commit the
	// changes or abort them and free memory.
	InsertTxs(blockHash common.Hash, blockHeight uint64, parentHash common.Hash, txs []*atomic.Tx) (common.Hash, error)

	// Returns an AtomicState corresponding to a block hash that has been inserted
	// but not Accepted or Rejected yet.
	GetVerifiedAtomicState(blockHash common.Hash) (AtomicState, error)

	// AtomicTrie returns the atomic trie managed by this backend.
	AtomicTrie() AtomicTrie

	// ApplyToSharedMemory applies the atomic operations that have been indexed into the trie
	// but not yet applied to shared memory for heights less than or equal to [lastAcceptedBlock].
	// This executes operations in the range [cursorHeight+1, lastAcceptedBlock].
	// The cursor is initially set by  MarkApplyToSharedMemoryCursor to signal to the atomic trie
	// the range of operations that were added to the trie without being executed on shared memory.
	ApplyToSharedMemory(lastAcceptedBlock uint64) error

	// MarkApplyToSharedMemoryCursor marks the atomic trie as containing atomic ops that
	// have not been executed on shared memory starting at [previousLastAcceptedHeight+1].
	// This is used when state sync syncs the atomic trie, such that the atomic operations
	// from [previousLastAcceptedHeight+1] to the [lastAcceptedHeight] set by state sync
	// will not have been executed on shared memory.
	MarkApplyToSharedMemoryCursor(previousLastAcceptedHeight uint64) error

	// SetLastAccepted is used after state-sync to reset the last accepted block.
	SetLastAccepted(lastAcceptedHash common.Hash)

	// IsBonus returns true if the block for atomicState is a bonus block
	IsBonus(blockHeight uint64, blockHash common.Hash) bool
}

AtomicBackend abstracts the verification and processing of atomic transactions

func NewAtomicBackend added in v0.9.0

func NewAtomicBackend(
	db *versiondb.Database, sharedMemory avalancheatomic.SharedMemory,
	bonusBlocks map[uint64]ids.ID, repo AtomicTxRepository,
	lastAcceptedHeight uint64, lastAcceptedHash common.Hash, commitInterval uint64,
) (AtomicBackend, error)

NewAtomicBackend creates an AtomicBackend from the specified dependencies

type AtomicState added in v0.9.0

type AtomicState interface {
	// Root of the atomic trie after applying the state change.
	Root() common.Hash
	// Accept applies the state change to VM's persistent storage
	// Changes are persisted atomically along with the provided [commitBatch].
	Accept(commitBatch database.Batch, requests map[ids.ID]*avalancheatomic.Requests) error
	// Reject frees memory associated with the state change.
	Reject() error
}

AtomicState is an abstraction created through AtomicBackend and can be used to apply the VM's state change for atomic txs or reject them to free memory. The root of the atomic trie after applying the state change is accessible through this interface as well.

type AtomicTrie added in v0.8.4

type AtomicTrie interface {
	// OpenTrie returns a modifiable instance of the atomic trie backed by trieDB
	// opened at hash.
	OpenTrie(hash common.Hash) (*trie.Trie, error)

	// UpdateTrie updates [tr] to inlude atomicOps for height.
	UpdateTrie(tr *trie.Trie, height uint64, atomicOps map[ids.ID]*avalancheatomic.Requests) error

	// Iterator returns an AtomicTrieIterator to iterate the trie at the given
	// root hash starting at [cursor].
	Iterator(hash common.Hash, cursor []byte) (AtomicTrieIterator, error)

	// LastCommitted returns the last committed hash and corresponding block height
	LastCommitted() (common.Hash, uint64)

	// TrieDB returns the underlying trie database
	TrieDB() *triedb.Database

	// Root returns hash if it exists at specified height
	// if trie was not committed at provided height, it returns
	// common.Hash{} instead
	Root(height uint64) (common.Hash, error)

	// LastAcceptedRoot returns the most recent accepted root of the atomic trie,
	// or the root it was initialized to if no new tries were accepted yet.
	LastAcceptedRoot() common.Hash

	// InsertTrie updates the trieDB with the provided node set and adds a reference
	// to root in the trieDB. Once InsertTrie is called, it is expected either
	// AcceptTrie or RejectTrie be called for the same root.
	InsertTrie(nodes *trienode.NodeSet, root common.Hash) error

	// AcceptTrie marks root as the last accepted atomic trie root, and
	// commits the trie to persistent storage if height is divisible by
	// the commit interval. Returns true if the trie was committed.
	AcceptTrie(height uint64, root common.Hash) (bool, error)

	// RejectTrie dereferences root from the trieDB, freeing memory.
	RejectTrie(root common.Hash) error
}

AtomicTrie maintains an index of atomic operations by blockchainIDs for every block height containing atomic transactions. The backing data structure for this index is a Trie. The keys of the trie are block heights and the values (leaf nodes) are the atomic operations applied to shared memory while processing the block accepted at the corresponding height.

type AtomicTrieIterator added in v0.8.4

type AtomicTrieIterator interface {
	// Next advances the iterator to the next node in the atomic trie and
	// returns true if there are more leaves to iterate
	Next() bool

	// Key returns the current database key that the iterator is iterating
	// returned []byte can be freely modified
	Key() []byte

	// Value returns the current database value that the iterator is iterating
	Value() []byte

	// BlockNumber returns the current block number
	BlockNumber() uint64

	// BlockchainID returns the current blockchain ID at the current block number
	BlockchainID() ids.ID

	// AtomicOps returns a map of blockchainIDs to the set of atomic requests
	// for that blockchainID at the current block number
	AtomicOps() *avalancheatomic.Requests

	// Error returns error, if any encountered during this iteration
	Error() error
}

AtomicTrieIterator is a stateful iterator that iterates the leafs of an AtomicTrie

func NewAtomicTrieIterator added in v0.8.4

func NewAtomicTrieIterator(trieIterator *trie.Iterator, codec codec.Manager) AtomicTrieIterator

type AtomicTxRepository added in v0.8.3

type AtomicTxRepository interface {
	GetIndexHeight() (uint64, error)
	GetByTxID(txID ids.ID) (*atomic.Tx, uint64, error)
	GetByHeight(height uint64) ([]*atomic.Tx, error)
	Write(height uint64, txs []*atomic.Tx) error
	WriteBonus(height uint64, txs []*atomic.Tx) error

	IterateByHeight(start uint64) database.Iterator
	Codec() codec.Manager
}

AtomicTxRepository defines an entity that manages storage and indexing of atomic transactions

type AvaxAPI added in v0.2.15

type AvaxAPI struct {
	// contains filtered or unexported fields
}

AvaxAPI offers Avalanche network related API methods

func (*AvaxAPI) GetAtomicTx added in v0.5.2

func (service *AvaxAPI) GetAtomicTx(r *http.Request, args *api.GetTxArgs, reply *FormattedTx) error

GetAtomicTx returns the specified transaction

func (*AvaxAPI) GetAtomicTxStatus added in v0.5.2

func (service *AvaxAPI) GetAtomicTxStatus(r *http.Request, args *api.JSONTxID, reply *client.GetAtomicTxStatusReply) error

GetAtomicTxStatus returns the status of the specified transaction

func (*AvaxAPI) GetUTXOs added in v0.3.14

func (service *AvaxAPI) GetUTXOs(r *http.Request, args *api.GetUTXOsArgs, reply *api.GetUTXOsReply) error

GetUTXOs gets all utxos for passed in addresses

func (*AvaxAPI) IssueTx added in v0.3.14

func (service *AvaxAPI) IssueTx(r *http.Request, args *api.FormattedTx, response *api.JSONTxID) error

func (*AvaxAPI) Version added in v0.5.4

func (service *AvaxAPI) Version(r *http.Request, _ *struct{}, reply *VersionReply) error

ClientVersion returns the version of the VM running

type Block

type Block struct {
	// contains filtered or unexported fields
}

Block implements the snowman.Block interface

func (*Block) Accept

func (b *Block) Accept(context.Context) error

Accept implements the snowman.Block interface

func (*Block) AtomicTxs

func (b *Block) AtomicTxs() []*atomic.Tx

func (*Block) Bytes

func (b *Block) Bytes() []byte

Bytes implements the snowman.Block interface

func (*Block) Height added in v0.3.17

func (b *Block) Height() uint64

Height implements the snowman.Block interface

func (*Block) ID

func (b *Block) ID() ids.ID

ID implements the snowman.Block interface

func (*Block) Parent

func (b *Block) Parent() ids.ID

Parent implements the snowman.Block interface

func (*Block) Reject

func (b *Block) Reject(context.Context) error

Reject implements the snowman.Block interface If [b] contains an atomic transaction, attempt to re-issue it

func (*Block) ShouldVerifyWithContext added in v0.12.10

func (b *Block) ShouldVerifyWithContext(context.Context) (bool, error)

ShouldVerifyWithContext implements the block.WithVerifyContext interface

func (*Block) String

func (b *Block) String() string

func (*Block) Timestamp added in v0.5.4

func (b *Block) Timestamp() time.Time

Timestamp implements the snowman.Block interface

func (*Block) Verify

func (b *Block) Verify(context.Context) error

Verify implements the snowman.Block interface

func (*Block) VerifyWithContext added in v0.12.10

func (b *Block) VerifyWithContext(ctx context.Context, proposerVMBlockCtx *block.Context) error

VerifyWithContext implements the block.WithVerifyContext interface

type BlockValidator added in v0.4.0

type BlockValidator interface {
	SyntacticVerify(b *Block, rules params.Rules) error
}

func NewBlockValidator added in v0.8.16

func NewBlockValidator(extDataHashes map[common.Hash]common.Hash) BlockValidator

type BuildGenesisReply added in v0.3.15

type BuildGenesisReply struct {
	Bytes    string              `json:"bytes"`
	Encoding formatting.Encoding `json:"encoding"`
}

BuildGenesisReply is the reply from BuildGenesis

type CorethLogger added in v0.8.15

type CorethLogger struct {
	gethlog.Logger
	// contains filtered or unexported fields
}

func InitLogger added in v0.8.15

func InitLogger(alias string, level string, jsonFormat bool, writer io.Writer) (CorethLogger, error)

InitLogger initializes logger with alias and sets the log level and format with the original os.StdErr interface along with the context logger.

func (*CorethLogger) SetLogLevel added in v0.8.15

func (c *CorethLogger) SetLogLevel(level string) error

SetLogLevel sets the log level of initialized log handler.

type EthPushGossiper added in v0.13.1

type EthPushGossiper struct {
	// contains filtered or unexported fields
}

EthPushGossiper is used by the ETH backend to push transactions issued over the RPC and added to the mempool to peers.

func (*EthPushGossiper) Add added in v0.13.1

func (e *EthPushGossiper) Add(tx *types.Transaction)

type Factory

type Factory struct{}

func (*Factory) New

func (*Factory) New(logging.Logger) (interface{}, error)

type FormattedTx added in v0.5.2

type FormattedTx struct {
	api.FormattedTx
	BlockHeight *json.Uint64 `json:"blockHeight,omitempty"`
}

type GetAcceptedFrontReply

type GetAcceptedFrontReply struct {
	Hash   common.Hash `json:"hash"`
	Number *big.Int    `json:"number"`
}

GetAcceptedFrontReply defines the reply that will be sent from the GetAcceptedFront API call

type GossipEthTx added in v0.12.5

type GossipEthTx struct {
	Tx *types.Transaction
}

func (*GossipEthTx) GossipID added in v0.12.10

func (tx *GossipEthTx) GossipID() ids.ID

type GossipEthTxMarshaller added in v0.12.10

type GossipEthTxMarshaller struct{}

func (GossipEthTxMarshaller) MarshalGossip added in v0.12.10

func (g GossipEthTxMarshaller) MarshalGossip(tx *GossipEthTx) ([]byte, error)

func (GossipEthTxMarshaller) UnmarshalGossip added in v0.12.10

func (g GossipEthTxMarshaller) UnmarshalGossip(bytes []byte) (*GossipEthTx, error)

type GossipEthTxPool added in v0.12.5

type GossipEthTxPool struct {
	// contains filtered or unexported fields
}

func NewGossipEthTxPool added in v0.12.5

func NewGossipEthTxPool(mempool *txpool.TxPool, registerer prometheus.Registerer) (*GossipEthTxPool, error)

func (*GossipEthTxPool) Add added in v0.12.5

func (g *GossipEthTxPool) Add(tx *GossipEthTx) error

Add enqueues the transaction to the mempool. Subscribe should be called to receive an event if tx is actually added to the mempool or not.

func (*GossipEthTxPool) GetFilter added in v0.12.5

func (g *GossipEthTxPool) GetFilter() ([]byte, []byte)

func (*GossipEthTxPool) Has added in v0.13.1

func (g *GossipEthTxPool) Has(txID ids.ID) bool

Has should just return whether or not the [txID] is still in the mempool, not whether it is in the mempool AND pending.

func (*GossipEthTxPool) IsSubscribed added in v0.13.3

func (g *GossipEthTxPool) IsSubscribed() bool

IsSubscribed returns whether or not the gossip subscription is active.

func (*GossipEthTxPool) Iterate added in v0.12.5

func (g *GossipEthTxPool) Iterate(f func(tx *GossipEthTx) bool)

func (*GossipEthTxPool) Subscribe added in v0.12.5

func (g *GossipEthTxPool) Subscribe(ctx context.Context)

type SnowmanAPI

type SnowmanAPI struct {
	// contains filtered or unexported fields
}

SnowmanAPI introduces snowman specific functionality to the evm

func (*SnowmanAPI) GetAcceptedFront

func (api *SnowmanAPI) GetAcceptedFront(ctx context.Context) (*GetAcceptedFrontReply, error)

GetAcceptedFront returns the last accepted block's hash and height

func (*SnowmanAPI) IssueBlock added in v0.3.7

func (api *SnowmanAPI) IssueBlock(ctx context.Context) error

IssueBlock to the chain

type StateSyncClient added in v0.8.10

type StateSyncClient interface {
	// methods that implement the client side of [block.StateSyncableVM]
	StateSyncEnabled(context.Context) (bool, error)
	GetOngoingSyncStateSummary(context.Context) (block.StateSummary, error)
	ParseStateSummary(ctx context.Context, summaryBytes []byte) (block.StateSummary, error)

	// additional methods required by the evm package
	ClearOngoingSummary() error
	Shutdown() error
	Error() error
}

func NewStateSyncClient added in v0.8.10

func NewStateSyncClient(config *stateSyncClientConfig) StateSyncClient

type StateSyncServer added in v0.8.10

type StateSyncServer interface {
	GetLastStateSummary(context.Context) (block.StateSummary, error)
	GetStateSummary(context.Context, uint64) (block.StateSummary, error)
}

func NewStateSyncServer added in v0.8.10

func NewStateSyncServer(config *stateSyncServerConfig) StateSyncServer

type StaticService

type StaticService struct{}

StaticService defines the static API services exposed by the evm

func (*StaticService) BuildGenesis

func (*StaticService) BuildGenesis(_ context.Context, args *core.Genesis) (*BuildGenesisReply, error)

BuildGenesis returns the UTXOs such that at least one address in [args.Addresses] is referenced in the UTXO.

type Syncer added in v0.8.10

type Syncer interface {
	Start(ctx context.Context) error
	Done() <-chan error
}

Syncer represents a step in state sync, along with Start/Done methods to control and monitor progress. Error returns an error if any was encountered.

type VM

type VM struct {

	// *chain.State helps to implement the VM interface by wrapping blocks
	// with an efficient caching layer.
	*chain.State

	peer.Network

	IsPlugin bool

	// State sync server and client
	StateSyncServer
	StateSyncClient
	// contains filtered or unexported fields
}

VM implements the snowman.ChainVM interface

func (*VM) Clock added in v0.2.12

func (vm *VM) Clock() *mockable.Clock

Clock implements the secp256k1fx interface

func (*VM) CodecRegistry added in v0.3.15

func (vm *VM) CodecRegistry() codec.Registry

CodecRegistry implements the secp256k1fx interface

func (*VM) CreateHandlers

func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error)

CreateHandlers makes new http handlers that can handle API calls

func (*VM) CreateStaticHandlers

func (vm *VM) CreateStaticHandlers(context.Context) (map[string]http.Handler, error)

CreateStaticHandlers makes new http handlers that can handle API calls

func (*VM) FormatAddress added in v0.3.14

func (vm *VM) FormatAddress(chainID ids.ID, addr ids.ShortID) (string, error)

FormatAddress takes in a chainID and a raw address and produces the formatted address

func (*VM) FormatLocalAddress added in v0.3.14

func (vm *VM) FormatLocalAddress(addr ids.ShortID) (string, error)

FormatLocalAddress takes in a raw address and produces the formatted address

func (*VM) GetAcceptedBlock added in v0.13.7

func (vm *VM) GetAcceptedBlock(ctx context.Context, blkID ids.ID) (snowman.Block, error)

GetAcceptedBlock attempts to retrieve block [blkID] from the VM. This method only returns accepted blocks.

func (*VM) GetActivationTime added in v0.7.0

func (vm *VM) GetActivationTime() time.Time

implements SnowmanPlusPlusVM interface

func (*VM) GetAtomicUTXOs added in v0.2.12

func (vm *VM) GetAtomicUTXOs(
	chainID ids.ID,
	addrs set.Set[ids.ShortID],
	startAddr ids.ShortID,
	startUTXOID ids.ID,
	limit int,
) ([]*avax.UTXO, ids.ShortID, ids.ID, error)

GetAtomicUTXOs returns the utxos that at least one of the provided addresses is referenced in.

func (*VM) GetBlockIDAtHeight added in v0.8.5

func (vm *VM) GetBlockIDAtHeight(_ context.Context, height uint64) (ids.ID, error)

GetBlockIDAtHeight returns the canonical block at [height]. Note: the engine assumes that if a block is not found at [height], then [database.ErrNotFound] will be returned. This indicates that the VM has state synced and does not have all historical blocks available.

func (*VM) HealthCheck added in v0.3.25

func (vm *VM) HealthCheck(context.Context) (interface{}, error)

Health returns nil if this chain is healthy. Also returns details, which should be one of: string, []byte, map[string]string

func (*VM) Initialize

func (vm *VM) Initialize(
	_ context.Context,
	chainCtx *snow.Context,
	db database.Database,
	genesisBytes []byte,
	upgradeBytes []byte,
	configBytes []byte,
	toEngine chan<- commonEng.Message,
	fxs []*commonEng.Fx,
	appSender commonEng.AppSender,
) error

Initialize implements the snowman.ChainVM interface

func (*VM) Logger added in v0.2.12

func (vm *VM) Logger() logging.Logger

Logger implements the secp256k1fx interface

func (*VM) NewBlockBuilder added in v0.7.0

func (vm *VM) NewBlockBuilder(notifyBuildBlockChan chan<- commonEng.Message) *blockBuilder

func (*VM) ParseAddress added in v0.2.12

func (vm *VM) ParseAddress(addrStr string) (ids.ID, ids.ShortID, error)

ParseAddress takes in an address and produces the ID of the chain it's for the ID of the address

func (*VM) ParseEthBlock added in v0.8.11

func (vm *VM) ParseEthBlock(b []byte) (*types.Block, error)

func (*VM) ParseLocalAddress added in v0.3.14

func (vm *VM) ParseLocalAddress(addrStr string) (ids.ShortID, error)

ParseLocalAddress takes in an address for this chain and produces the ID

func (*VM) ParseServiceAddress added in v0.12.5

func (vm *VM) ParseServiceAddress(addrStr string) (ids.ShortID, error)

ParseServiceAddress get address ID from address string, being it either localized (using address manager, doing also components validations), or not localized. If both attempts fail, reports error from localized address parsing

func (*VM) SetPreference

func (vm *VM) SetPreference(ctx context.Context, blkID ids.ID) error

SetPreference sets what the current tail of the chain is

func (*VM) SetState added in v0.8.5

func (vm *VM) SetState(_ context.Context, state snow.State) error

func (*VM) Shutdown

func (vm *VM) Shutdown(context.Context) error

Shutdown implements the snowman.ChainVM interface

func (*VM) VerifyHeightIndex added in v0.8.5

func (vm *VM) VerifyHeightIndex(context.Context) error

VerifyHeightIndex always returns a nil error since the index is maintained by vm.blockChain.

func (*VM) Version added in v0.5.4

func (vm *VM) Version(context.Context) (string, error)

type VersionReply added in v0.5.4

type VersionReply struct {
	Version string `json:"version"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL