Passa al contenuto principale

Cross-VM Interoperability

L'architettura triple-VM di QoreChain (EVM, CosmWasm, SVM) consente agli smart contract su qualsiasi macchina virtuale di comunicare con i contratti su qualsiasi altra VM. Il modulo x/crossvm fornisce percorsi di messaggistica sia sincroni che asincroni.

nota

Gli endpoint seguenti utilizzano per impostazione predefinita un nodo locale. Sulla mainnet, usa gli endpoint RPC di qorechain-vladi (Cosmos RPC 26657, EVM JSON-RPC 8545); la testnet è qorechain-diana.


Panoramica dell'architettura

EVM (Solidity) CosmWasm (Rust/Wasm) SVM (BPF)
| | |
|--- sync (precompile) ->| |
| | |
|<-- async (EndBlocker) -|-- async (EndBlocker) ->|
| | |
|<------------ async (EndBlocker) ----------------|
PercorsoDirezioneTempisticaMeccanismo
SincronoEVM verso CosmWasmStessa transazionePrecompile a 0x0000...0901
AsincronoCosmWasm verso EVMBlocco successivoMsgCrossVMCall via EndBlocker
AsincronoSVM verso qualsiasi VMBlocco successivoMsgCrossVMCall via EndBlocker
AsincronoQualsiasi verso SVMBlocco successivoMsgCrossVMCall via EndBlocker

Percorso sincrono (EVM verso CosmWasm)

Il percorso sincrono utilizza una precompile EVM all'indirizzo 0x0000000000000000000000000000000000000901. Questo consente ai contratti Solidity di chiamare i contratti CosmWasm e di ricevere una risposta all'interno della stessa transazione.

Esempio Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface ICrossVM {
function call(bytes calldata payload) external returns (bytes memory);
}

contract CrossVMCaller {
ICrossVM constant CROSSVM = ICrossVM(0x0000000000000000000000000000000000000901);

function callCosmWasmContract(
string memory cosmwasmAddr,
string memory executeMsg,
uint256 funds
) external returns (bytes memory) {
bytes memory payload = abi.encode(cosmwasmAddr, executeMsg, funds);
return CROSSVM.call(payload);
}
}

La precompile esegue il contratto CosmWasm immediatamente e restituisce il risultato. Costo del gas: 50.000 base + costo di esecuzione.


Percorso asincrono

Tutte le altre direzioni cross-VM utilizzano la coda di messaggi asincrona. I messaggi vengono inviati in un blocco ed elaborati dall'EndBlocker nel blocco successivo.

CLI

# CosmWasm to EVM
qorechaind tx crossvm call \
--source-vm cosmwasm \
--target-vm evm \
--target-contract 0x1234...abcd \
--payload '{"method":"transfer","params":["0xRecipient",100]}' \
--from mykey \
-y

# SVM to CosmWasm
qorechaind tx crossvm call \
--source-vm svm \
--target-vm cosmwasm \
--target-contract qor1contractaddr... \
--payload '{"execute":{"action":{}}}' \
--from mykey \
-y

# EVM to SVM (async)
qorechaind tx crossvm call \
--source-vm evm \
--target-vm svm \
--target-contract <program-id-base58> \
--payload '0a0b0c...' \
--from mykey \
-y

Ciclo di vita del messaggio

Ogni messaggio cross-VM attraversa un insieme definito di stati:

Submitted --> Pending --> Executed
|
+--> Failed
|
+--> Timed Out
StatoDescrizione
SubmittedMessaggio accettato nella coda
PendingIn attesa di esecuzione nel passaggio successivo dell'EndBlocker
ExecutedContratto target chiamato con successo; risposta registrata
FailedL'esecuzione del contratto target è stata annullata (revert); errore registrato
Timed OutIl messaggio ha superato queue_timeout_blocks senza esecuzione

Parametri

ParametroValoreDescrizione
max_message_size65.536 byteDimensione massima del payload per messaggio
max_queue_size1.000Numero massimo di messaggi in attesa nella coda
queue_timeout_blocks100Blocchi prima che un messaggio non elaborato vada in timeout

Eventi

Il modulo x/crossvm emette i seguenti eventi:

EventoAttributiDescrizione
crossvm_requestmessage_id, source_vm, target_vm, target_contract, senderNuovo messaggio cross-VM inviato
crossvm_responsemessage_id, status, resultMessaggio eseguito (successo o fallimento)
crossvm_timeoutmessage_id, source_vm, target_vmMessaggio scaduto senza esecuzione

Sottoscrivi gli eventi via WebSocket:

wscat -c ws://localhost:26657/websocket
> {"jsonrpc":"2.0","method":"subscribe","params":["tm.event='Tx' AND crossvm_request.message_id EXISTS"],"id":1}

Interrogazione dei messaggi

CLI

# Query a specific message by ID
qorechaind query crossvm message <message-id>

# List all pending messages
qorechaind query crossvm pending

# List messages by sender
qorechaind query crossvm messages-by-sender <address>

JSON-RPC

curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qor_getCrossVMMessage",
"params": ["<message-id>"],
"id": 1
}'

Formato della risposta

{
"message_id": "crossvm-00000042",
"source_vm": "cosmwasm",
"target_vm": "evm",
"target_contract": "0x1234...abcd",
"sender": "qor1sender...",
"payload": "...",
"status": "executed",
"result": "0x...",
"submitted_height": 12345,
"executed_height": 12346
}

Considerazioni di progettazione

Atomicità: le chiamate sincrone (EVM verso CosmWasm tramite precompile) sono atomiche — se una delle due parti effettua un revert, l'intera transazione viene annullata. Le chiamate asincrone non sono atomiche tra blocchi diversi; progetta i tuoi contratti per gestire correttamente gli stati Failed e Timed Out.

Ordinamento: i messaggi nella coda vengono elaborati FIFO all'interno di ogni passaggio dell'EndBlocker. Non è garantito alcun ordinamento tra diverse VM di origine.

Codifica del payload: il formato del payload dipende dalla VM target:

  • Target EVM: chiamate di funzione codificate in ABI
  • Target CosmWasm: messaggi execute codificati in JSON
  • Target SVM: dati delle istruzioni BPF codificati in esadecimale

Prossimi passi