본문으로 건너뛰기

크로스 VM 상호운용성

QoreChain의 트리플 VM 아키텍처(EVM, CosmWasm, SVM)는 어떤 가상 머신의 스마트 컨트랙트든 다른 모든 VM의 컨트랙트와 통신할 수 있게 합니다. x/crossvm 모듈은 동기 및 비동기 메시징 경로를 모두 제공합니다.

노트

아래 엔드포인트는 기본적으로 로컬 노드를 사용합니다. 메인넷에서는 qorechain-vladi RPC 엔드포인트(Cosmos RPC 26657, EVM JSON-RPC 8545)를 사용하세요. 테스트넷은 **qorechain-diana**입니다.


아키텍처 개요

EVM (Solidity) CosmWasm (Rust/Wasm) SVM (BPF)
| | |
|--- sync (precompile) ->| |
| | |
|<-- async (EndBlocker) -|-- async (EndBlocker) ->|
| | |
|<------------ async (EndBlocker) ----------------|
경로방향타이밍메커니즘
동기(Synchronous)EVM에서 CosmWasm으로동일 트랜잭션0x0000...0901의 프리컴파일
비동기(Asynchronous)CosmWasm에서 EVM으로다음 블록EndBlocker를 통한 MsgCrossVMCall
비동기(Asynchronous)SVM에서 임의 VM으로다음 블록EndBlocker를 통한 MsgCrossVMCall
비동기(Asynchronous)임의 VM에서 SVM으로다음 블록EndBlocker를 통한 MsgCrossVMCall

동기 경로 (EVM에서 CosmWasm으로)

동기 경로는 주소 0x0000000000000000000000000000000000000901의 EVM 프리컴파일을 사용합니다. 이를 통해 Solidity 컨트랙트가 CosmWasm 컨트랙트를 호출하고 동일한 트랜잭션 내에서 응답을 받을 수 있습니다.

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);
}
}

프리컴파일은 CosmWasm 컨트랙트를 즉시 실행하고 결과를 반환합니다. 가스 비용: 기본 50,000 + 실행 비용.


비동기 경로

다른 모든 크로스 VM 방향은 비동기 메시지 큐를 사용합니다. 메시지는 한 블록에서 제출되고 다음 블록의 EndBlocker에 의해 처리됩니다.

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

메시지 라이프사이클

모든 크로스 VM 메시지는 정의된 상태 집합을 거쳐 전환됩니다:

Submitted --> Pending --> Executed
|
+--> Failed
|
+--> Timed Out
상태설명
Submitted메시지가 큐에 수락됨
Pending다음 EndBlocker 패스에서 실행 대기 중
Executed대상 컨트랙트가 성공적으로 호출됨; 응답 기록됨
Failed대상 컨트랙트 실행이 되돌려짐; 오류 기록됨
Timed Out메시지가 실행 없이 queue_timeout_blocks를 초과함

파라미터

파라미터설명
max_message_size65,536 bytes메시지당 최대 페이로드 크기
max_queue_size1,000큐에 대기 중인 최대 메시지 수
queue_timeout_blocks100처리되지 않은 메시지가 타임아웃되기까지의 블록 수

이벤트

x/crossvm 모듈은 다음 이벤트를 방출합니다:

이벤트속성설명
crossvm_requestmessage_id, source_vm, target_vm, target_contract, sender새 크로스 VM 메시지 제출됨
crossvm_responsemessage_id, status, result메시지 실행됨(성공 또는 실패)
crossvm_timeoutmessage_id, source_vm, target_vm메시지가 실행 없이 만료됨

WebSocket을 통해 이벤트를 구독하세요:

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

메시지 조회

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
}'

응답 형식

{
"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
}

설계 고려 사항

원자성: 동기 호출(프리컴파일을 통한 EVM에서 CosmWasm으로)은 원자적입니다 — 어느 한쪽이 되돌려지면 전체 트랜잭션이 되돌려집니다. 비동기 호출은 블록 간에 원자적이지 않습니다; FailedTimed Out 상태를 우아하게 처리하도록 컨트랙트를 설계하세요.

순서: 큐의 메시지는 각 EndBlocker 패스 내에서 FIFO로 처리됩니다. 서로 다른 소스 VM 간에 보장된 순서는 없습니다.

페이로드 인코딩: 페이로드 형식은 대상 VM에 따라 다릅니다:

  • EVM 대상: ABI 인코딩된 함수 호출
  • CosmWasm 대상: JSON 인코딩된 execute 메시지
  • SVM 대상: Hex 인코딩된 BPF 명령 데이터

다음 단계