Saltar al contenido principal

Recuperar una entrada del libro de contabilidad del código del contrato usando el SDK de Python

Cuando despliegas un contrato, primero el código es "instalado" (es decir, se carga en la blockchain). Esto crea una LedgerEntry que contiene el byte-código Wasm, que se identifica de manera única por su hash (es decir, el hash del código cargado en sí). Luego, cuando el contrato es "desplegado", creamos una LedgerEntry con una referencia al hash de ese código. Así que obtener el código del contrato es un proceso de dos pasos:

  1. Primero, buscamos el contrato en sí, para ver qué hash de código está referenciando.
  2. Luego, podemos buscar el byte-código Wasm en bruto usando ese hash.
from stellar_sdk import xdr, Address

def get_ledger_key_contract_code(contract_id: str) -> str:
ledger_key = xdr.LedgerKey(
type=xdr.LedgerEntryType.CONTRACT_DATA,
contract_data=xdr.LedgerKeyContractData(
contract=Address(contract_id).to_xdr_sc_address(),
key=xdr.SCVal(xdr.SCValType.SCV_LEDGER_KEY_CONTRACT_INSTANCE),
durability=xdr.ContractDataDurability.PERSISTENT
)
)
return ledger_key.to_xdr()

print(
get_ledger_key_contract_code(
"CCPYZFKEAXHHS5VVW5J45TOU7S2EODJ7TZNJIA5LKDVL3PESCES6FNCI"
)
)
# OUTPUT: AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB

Luego tomamos nuestra salida de esta función y la usamos como el elemento en el parámetro del arreglo keys en nuestra llamada al método getLedgerEntries.

{
"jsonrpc": "2.0",
"id": 8675309,
"method": "getLedgerEntries",
"params": {
"keys": ["AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB"]
}
}

Y la respuesta que recibimos contiene el LedgerEntryData que se puede usar para encontrar el hash que debemos usar para solicitar el byte-código Wasm. Este hash es el LedgerKey que se ha asociado con el código del contrato desplegado.

{
"jsonrpc": "2.0",
"id": 8675309,
"result": {
"entries": [
{
"key": "AAAABgAAAAGfjJVEBc55drW3U87N1Py0Rw0/nlqUA6tQ6r28khEl4gAAABQAAAAB",
"xdr": "AAAABgAAAAAAAAABn4yVRAXOeXa1t1POzdT8tEcNP55alAOrUOq9vJIRJeIAAAAUAAAAAQAAABMAAAAA5DNtbckOGVRsNVb8L7X/lIhAOy2o5G6GkLKXvc7W8foAAAAA",
"lastModifiedLedgerSeq": 261603
}
],
"latestLedger": 262322
}
}

Ahora toma el campo xdr del objeto result de la respuesta anterior y crea un LedgerKey a partir del hash contenido dentro.

from stellar_sdk import xdr

def get_ledger_key_wasm_id(contract_code_ledger_entry_data: str) -> str:
# First, we dig the wasm_id hash out of the xdr we received from RPC
contract_code_wasm_hash = xdr.LedgerEntryData.from_xdr(
contract_code_ledger_entry_data
).contract_data.val.instance.executable.wasm_hash
# Now, we can create the `LedgerKey` as we've done in previous examples
ledger_key = xdr.LedgerKey(
type=xdr.LedgerEntryType.CONTRACT_CODE,
contract_code=xdr.LedgerKeyContractCode(
hash=contract_code_wasm_hash
),
)
return ledger_key.to_xdr()

print(
get_ledger_key_wasm_id(
"AAAABgAAAAAAAAABn4yVRAXOeXa1t1POzdT8tEcNP55alAOrUOq9vJIRJeIAAAAUAAAAAQAAABMAAAAA5DNtbckOGVRsNVb8L7X/lIhAOy2o5G6GkLKXvc7W8foAAAAA"
)
)
# OUTPUT: AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6

Ahora, finalmente tenemos un LedgerKey que corresponde al byte-código Wasm que ha sido desplegado bajo el ContractId con el que comenzamos hace tanto tiempo. Este LedgerKey se puede usar en una solicitud final al punto final Stellar-RPC.

{
"jsonrpc": "2.0",
"id": 8675309,
"method": "getLedgerEntries",
"params": {
"keys": ["AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6"]
}
}

Y la respuesta que obtenemos contiene (aún más) LedgerEntryData que podemos decodificar y analizar para obtener el byte-código del contrato desplegado y real. Dejaremos ese ejercicio en tus manos. Puedes ver lo que contiene usando la "Página Ver XDR" del Stellar Lab.

{
"jsonrpc": "2.0",
"id": 8675309,
"result": {
"entries": [
{
"key": "AAAAB+QzbW3JDhlUbDVW/C+1/5SIQDstqORuhpCyl73O1vH6",
"xdr": "AAAABwAAAADkM21tyQ4ZVGw1Vvwvtf+UiEA7LajkboaQspe9ztbx+gAAAkgAYXNtAQAAAAEVBGACfn4BfmADfn5+AX5gAAF+YAAAAhkEAWwBMAAAAWwBMQAAAWwBXwABAWwBOAAAAwUEAgMDAwUDAQAQBhkDfwFBgIDAAAt/AEGAgMAAC38AQYCAwAALBzUFBm1lbW9yeQIACWluY3JlbWVudAAEAV8ABwpfX2RhdGFfZW5kAwELX19oZWFwX2Jhc2UDAgqnAQSSAQIBfwF+QQAhAAJAAkACQEKOutCvhtQ5QgEQgICAgABCAVINAEKOutCvhtQ5QgEQgYCAgAAiAUL/AYNCBFINASABQiCIpyEACyAAQQFqIgBFDQFCjrrQr4bUOSAArUIghkIEhCIBQgEQgoCAgAAaQoSAgICgBkKEgICAwAwQg4CAgAAaIAEPCwAACxCFgICAAAALCQAQhoCAgAAACwQAAAALAgALAHMOY29udHJhY3RzcGVjdjAAAAAAAAAAQEluY3JlbWVudCBpbmNyZW1lbnRzIGFuIGludGVybmFsIGNvdW50ZXIsIGFuZCByZXR1cm5zIHRoZSB2YWx1ZS4AAAAJaW5jcmVtZW50AAAAAAAAAAAAAAEAAAAEAB4RY29udHJhY3RlbnZtZXRhdjAAAAAAAAAAFAAAAAAAbw5jb250cmFjdG1ldGF2MAAAAAAAAAAFcnN2ZXIAAAAAAAAGMS43Ni4wAAAAAAAAAAAACHJzc2RrdmVyAAAALzIwLjMuMSNiYTA0NWE1N2FmOTcxZmM4M2U0NzU3NDZiNTlhNTAzYjdlZjQxNjQ5AA==",
"lastModifiedLedgerSeq": 368441,
"liveUntilLedgerSeq": 2442040
}
],
"latestLedger": 370940
}
}