jQuery(function($){ $('.logo_container a').attr('href','https://www.google.com'); });

CROATd JSON RPC API

Us heu preguntat mai com es fa per interactuar amb una blockchain? El wallet és una porta que interactua amb la blockchain, en el cas del CROAT tenim l’aplicació CROATCore, però al darrera hi ha unes aplicacions més bàsiques que envien instruccions i consultes per obtenir informació o escriure’n de nova.

En aquest apartat veurem com utilitzar la API del “croatd” mitjançant JSONRPC i així poder executar consultes directament a la blockchain de CROAT.

Tractarem les diferents consultes disponibles i veurem com executar els exemples amb instruccions utilitzant cURL, des de la línia de comandes del propi node, o utilitzant Postman des d’un equip remot ja que disposa d’una interfície gràfica.

HABILITAR RPC

Per tal de poder començar tindrem d’editar l’arxiu de configuració “configs/croat.conf“. En el nostre cas ho fem en un servidor (Ubuntu Server 16.04)

nano configs/croat.conf

Afegirem la següent línia

rpc-bind-ip=0.0.0.0

Mirem d’arrencar croatd

./croatd --config-file configs/croat.conf

Si tot va bé podem sortir amb “exit” i arrancar croatd de fons, deixarem un arxiu de log a la mateixa carpeta per si el volem revisar en algun moment.

nohup /home/ubuntu/Croat/croatd --config-file /home/ubuntu/Croat/configs/croat.conf --log-file /home/ubuntu/Croat/croatd.log > /dev/null 2>&1 &

Per tal de assegurar-nos que estem acceptant connexions RPC per el port 46348 executem la següent comanda

netstat -ntlp

El port 46348 ha de sortir amb 0.0.0.0:*

cURL JSONRPC

Les proves més simples que podem fer en aquests moments per saber si funciona són des del propi servidor, utilitzarem curl per enviar una consulta i esperarem la resposta, la documentació ens diu que l’instrucció ha de tenir el següent format:

curl -s -X POST http://<ip>:<port>/json_rpc -H 'Content-Type: application/json-rpc' -d '{ "method": "<method>","params": {<params>},"jsonrpc": "2.0", "id": "<id>"}'

<ip>: Ip del servidor, si es ell mateix cal posar 127.0.0.1
<port>: Port on tenim el servei RPC, en el nostre cas 46348
<method>: Serà la instrucció que cridem, el mètode
<params>: Algunes instruccions necessiten paràmetres d’entrada per donar una sortida, imaginem un filtre per data, la data actuarà com a parametre d’entrada i segons aquesta tindrem diferents sortides
<id>: Posarem un nom com a identificador

A continuació executem la nostra primera prova amb el mètode (getblockcount), que ens retornarà l’altura de la cadena de blocks.

curl -s -X POST http://127.0.0.1:46348/json_rpc -H 'Content-Type: application/json-rpc' -d '{"method":"getblockcount","params":{},"jsonrpc":"2.0","id":"json_test"}'

La sortida ens retorna 2 resultats

count: 539623, el valor que volíem saber
status: OK, ha finalitzat sense errors

POSTMAN

El programa POSTMAN ens permet, mitjançant una interfície gràfica, fer proves d’una API, el podem descarregar per diferents plataformes des de https://www.getpostman.com/apps. Un cop instal·lat caldrà que ens registrem per poder executar el programa.

Des del menú (File / Import) podem importar instruccions, fins i tot les fetes amb cURL

Només cal seleccionar (Paste Raw Text) i enganxar l’instrucció. Atenció amb una cosa, la IP ja no és 127.0.0.1, tindrem de posar la ip del servidor/equip on tinguem el croatd funcionant.

curl -s -X POST http://192.168.1.20:46348/json_rpc -H 'Content-Type: application/json-rpc' -d '{"method":"getblockcount","params":{},"jsonrpc":"2.0","id":"json_test"}'

Si tot ha anat bé ja tindrem la instrucció preparada. A l’apartat (Body) de la part superior tenim el “method”, “params”, “id”. Cal fer clic a (Send) per executar. A l’apartat (Body) de la part inferior tenim el resultat.

LLISTAT DE MÈTODES (JSONRPC)

A continuació revisem els diferents mètodes disponibles dins l’aplicació “croatd


  • getblockcount

Descripció: El mètode getblockcount retorna el nombre de blocs de la cadena blockchain
Paràmetres: Cap
Resposta: El nombre de blocs de la blockchain

Exemple getblockcount (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"getblockcount","params":{},"jsonrpc":"2.0","id":"json_test"}'

Exemple getblockcount (sortida)

{
    "id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "count": 546710,
        "status": "OK"
    }
}

  • on_getblockhash

Descripció: El mètode on_getblockhash retorna el hash d’un bloc a partir de la seva altura
Paràmetres: Altura del bloc
Resposta: El hash del bloc

Exemple on_getblockhash (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"on_getblockhash","params":[548181],"jsonrpc":"2.0","id":"json_test"}'

Exemple on_getblockhash (sortida)

{
    "id": "json_test",
    "jsonrpc": "2.0",
    "result": "035cf1d4df3a1469392d72fc367e02fd564272b1a78d915687dd648a42dc7c42"
}

  • getlastblockheader

Descripció: El mètode getlastblockheader retorna informació de la capçalera de l’últim bloc trobat.
Paràmetres: Cap
Resposta: Una estructura “block_header” amb diferents paràmetres i informació

"block_header": { 
"depth": El nombre de blocs posteriors al bloc actual, un nombre elevat significa que es un bloc antic, 
"difficulty": La dificultat de la blockchain CROAT segons el poder de minatge, 
"hash": Valor hash d'aquest bloc, 
"height": Altura de la cadena, total de blocs que precedeixen el bloc actual, 
"major_version": La versió màxima del protocol a aquesta altura de la cadena, 
"minor_version": La versió mínima del protocol a aquesta altura de la cadena, 
"nonce": El valor criptografic aleatòri d'un sol us que s'utilitza per resoldre un bloc de CROAT, 
"orphan_status": Valor (true/false). Normalment (false), si (true) vol dir que el 
                                         block no forma part de la cadena de blocs mes llarga, 
"prev_hash": El hash del block anterior d'aquest bloc, 
"reward": La recompensa en format d'unitats atòmiques. 1 CROAT = 1^11, 
"timestamp": La hora en format unix en que s'ha escrit el bloc dins la blockchain

Exemple getlastblockheader (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"getlastblockheader","params":{},"jsonrpc":"2.0","id":"json_test"}'

Exemple getlastblockheader (sortida)

{
    "id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "block_header": {
            "depth": 0,
            "difficulty": 1537886616,
            "hash": "035cf1d4df3a1469392d72fc367e02fd564272b1a78d915687dd648a42dc7c42",
            "height": 548181,
            "major_version": 3,
            "minor_version": 0,
            "nonce": 2697998417,
            "orphan_status": false,
            "prev_hash": "086f4b8e38408f9ad12aef0094df41a3e0daa2f5cb5fef949c25679d2834b525",
            "reward": 4828666787196,
            "timestamp": 1536181249
        },
        "status": "OK"
    }
}

  • getblockheaderbyhash

Descripció: El mètode getblockheaderbyhash retorna informació de la capçalera d’un bloc a partir del seu hash.
Paràmetres: hash del bloc a retornar
Resposta: Una estructura “block_header” amb diferents paràmetres i informació

"block_header": { 
"depth": El nombre de blocs posteriors al bloc actual, un nombre elevat significa que es un bloc antic, 
"difficulty": La dificultat de la blockchain CROAT segons el poder de minatge, 
"hash": Valor hash d'aquest bloc, 
"height": Altura de la cadena, total de blocs que precedeixen el bloc actual, 
"major_version": La versió màxima del protocol a aquesta altura de la cadena, 
"minor_version": La versió mínima del protocol a aquesta altura de la cadena, 
"nonce": El valor criptografic aleatòri d'un sol us que s'utilitza per resoldre un bloc de CROAT, 
"orphan_status": Valor (true/false). Normalment (false), si (true) vol dir que el 
                                         block no forma part de la cadena de blocs mes llarga, 
"prev_hash": El hash del block anterior d'aquest bloc, 
"reward": La recompensa en format d'unitats atòmiques. 1 CROAT = 1^11, 
"timestamp": La hora en format unix en que s'ha escrit el bloc dins la blockchain

Exemple getblockheaderbyhash (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"getblockheaderbyhash","params":{"hash":"035cf1d4df3a1469392d72fc367e02fd564272b1a78d915687dd648a42dc7c42"},"jsonrpc":"2.0","id":"json_test"}'

Exemple getblockheaderbyhash (sortida)

{
    "id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "block_header": {
            "depth": 23,
            "difficulty": 1537886616,
            "hash": "035cf1d4df3a1469392d72fc367e02fd564272b1a78d915687dd648a42dc7c42",
            "height": 548181,
            "major_version": 3,
            "minor_version": 0,
            "nonce": 2697998417,
            "orphan_status": false,
            "prev_hash": "086f4b8e38408f9ad12aef0094df41a3e0daa2f5cb5fef949c25679d2834b525",
            "reward": 4828666787196,
            "timestamp": 1536181249
        },
        "status": "OK"
    }
}

  • getblockheaderbyheight

Descripció: El mètode getblockheaderbyheight retorna informació de la capçalera d’un bloc a partir de la seva altura dins la blockchain
Paràmetres: Altura de la cadena del bloc a retornar
Resposta: Una estructura “block_header” amb diferents paràmetres i informació

"block_header": { 
"depth": El nombre de blocs posteriors al bloc actual, un nombre elevat significa que es un bloc antic, 
"difficulty": La dificultat de la blockchain CROAT segons el poder de minatge, 
"hash": Valor hash d'aquest bloc, 
"height": Altura de la cadena, total de blocs que precedeixen el bloc actual, 
"major_version": La versió màxima del protocol a aquesta altura de la cadena, 
"minor_version": La versió mínima del protocol a aquesta altura de la cadena, 
"nonce": El valor criptografic aleatòri d'un sol us que s'utilitza per resoldre un bloc de CROAT, 
"orphan_status": Valor (true/false). Normalment (false), si (true) vol dir que el 
                                         block no forma part de la cadena de blocs mes llarga, 
"prev_hash": El hash del block anterior d'aquest bloc, 
"reward": La recompensa en format d'unitats atòmiques. 1 CROAT = 1^11, 
"timestamp": La hora en format unix en que s'ha escrit el bloc dins la blockchain

Exemple getblockheaderbyheight (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"getblockheaderbyheight","params":{"hash":548181},"jsonrpc":"2.0","id":"json_test"}'

Exemple getblockheaderbyheight (sortida)

{
    "id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "block_header": {
            "depth": 31,
            "difficulty": 1537886616,
            "hash": "035cf1d4df3a1469392d72fc367e02fd564272b1a78d915687dd648a42dc7c42",
            "height": 548181,
            "major_version": 3,
            "minor_version": 0,
            "nonce": 2697998417,
            "orphan_status": false,
            "prev_hash": "086f4b8e38408f9ad12aef0094df41a3e0daa2f5cb5fef949c25679d2834b525",
            "reward": 4828666787196,
            "timestamp": 1536181249
        },
        "status": "OK"
    }
}

  • getblocktemplate

Descripció: El mètode getblocktemplate una plantilla amb diferents valors per poder minar un nou bloc
Paràmetres: wallet_address (Wallet on rebre la recompensa si es mina correctament el bloc), reserve_size (Valor enter <= 255 referent a l’espai extra reservat a la plantilla, poden ser dades arbitràries que poden estar incrustades en una transacció)
Resposta: Diferents paràmetres i informació

"blocktemplate_blob": Mostra en que intentem minar un nou bloc, 
"difficulty": La dificultat de la blockchain CROAT segons el poder de minatge, 
"height": Altura de la cadena, total de blocs que precedeixen el bloc actual, 
"reserved_offset": Espai reservat

Exemple getblocktemplate (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"getblocktemplate","params":{"wallet_address":"CsbWWpa76r2L89jfBEUuGn1frVz848JbNgC8h7pMJs1s7BfkfeCpxXLiVNiph9JS6E7nt8Veg2YHfL5rxDgkVqwb6n8ZpGi","reserve_size":60},"jsonrpc":"2.0","id":"json_test"}'

Exemple getblocktemplate (sortida)

{
    "id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "blocktemplate_blob": "030062c6d5be0cebaacdce07b7641a3f31b2fe706f821a4bb4283c2818f2dd14950a0000d9c5c6dc05000000000000000000000000000000000000000000000000000000000000000000000000010000000023032100000000000000000000000000000000000000000000000000000000000000000001c7c72101ffc0c7210797830c0231c95217b94d34ca929dada4161f76e5662e6c5f3e84b3933dabee44e4a5a347c09fab03027eae07a614b9f17f8b8b9ab5257b68b491bd34a6bbb33554f4dacdde20c3d77d80d293ad0302a40f43fed4c916c66131ad1fbe565bbdecb780941a146c42716e7cea103cf42980a8d6b907024a95dcdc5998963c312077180ac3d3a7fb2f35d2f5cfcaee4f2ea3745ce82ab88090dfc04a0244eed9f6f0013859c4daa2bb58965b214e9a7b25342878b5751afb141206e2fa8080dd9da417022bcf91c913a4f9daff9ebf2bfb9479c4a43a21c692027a4f8f482bc437d0fd0e8080d194b57402e9f5e9d5b738fc1c392cad2cfadf0ac3cbc74272774cc3af57d2c139a39037035f01643d394ee2ebfb338ab5c24ae5479b5ba90184f974e2bbbc3adbc236585a7377023c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e66318bbec04e30124004549295180175164a5dc3b183bf7ea479dac2a65f97197f72104134cc3f900acb63287cd6c298501ca327642634c3243f5a95fd76ef3",
        "difficulty": 1775844290,
        "height": 549824,
        "reserved_offset": 430,
        "status": "OK"
    }
}

  • f_blocks_list_json

Descripció: El mètode f_blocks_list_json retorna un petit resum dels últims 30 blocs a partir d’una altura determinada
Paràmetres: Altura del bloc inicial
Resposta: Una estructura “blocks” amb diferents paràmetres i informació

"blocks": [
            {
                "cumul_size": Tamany acumulat del bloc i les seves referències,
                "difficulty": La dificultat de la blockchain CROAT segons el poder de minatge,
                "hash": "Valor hash d'aquest bloc",
                "height": Altura de la cadena, total de blocs que precedeixen el bloc actual,
                "timestamp": La hora en format unix en que s'ha escrit el bloc dins la blockchain,
                "tx_count": Total de transaccions dins el bloc
            },

Exemple f_blocks_list_json (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"f_blocks_list_json","params":{"height":60},"jsonrpc":"2.0","id":"json_test"}'

Exemple f_blocks_list_json (sortida)

{"id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "blocks": [
            {
                "cumul_size": 463,
                "difficulty": 28238,
                "hash": "b25862f7723a4e5533949b2b9ddd0c36685515f8bb4ce205345dc0e267d24259",
                "height": 60,
                "timestamp": 1502834242,
                "tx_count": 1
            },
            {
                "cumul_size": 463,
                "difficulty": 27921,
                "hash": "1e9d8bfc2230ee86199553538584a0df99535532ebae7c872f386dce405d5064",
                "height": 59,
                "timestamp": 1502834231,
                "tx_count": 1
            },
           .........................................................
           /////////////////////////////////////////////////////////
           .........................................................
            {
                "cumul_size": 426,
                "difficulty": 31247,
                "hash": "c0fd832cc6ef0bf40c594923c1a1229dfa4dafcb6c7151c580edf988335226ff",
                "height": 31,
                "timestamp": 1502832241,
                "tx_count": 1
            },
            {
                "cumul_size": 463,
                "difficulty": 30833,
                "hash": "dd6a5fd388e52e64351e038b1e0a4ad037a0d8bf034ed0bf10a319d170ce6355",
                "height": 30,
                "timestamp": 1502832221,
                "tx_count": 1
            }
        ],
        "status": "OK"
    }
}

  • f_get_blockchain_settings

Descripció: El mètode f_get_blockchain_settings retorna informació de l’arxiu de configuració utilitzat
Paràmetres: Cap

Resposta: Una estructura “result” amb diferents paràmetres i informació

"result": {
        "base_coin": {
            "git": URL del repositori base,
            "name": Nom de la criptomoneda base
        },
        "core": {
            "BYTECOIN_NETWORK": S'utilitza per no barrejar dues xarxes diferents,
            "CHECKPOINTS": Punts de verificació. Format: HEIGHT:HASH,
            "CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE": La mida màxima d'un bloc per no tenir penalització,
            "CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1": La mida màxima d'un bloc per no tenir penalització, utilitzat en versió (v1) de la blockchain,
            "CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2": La mida màxima d'un bloc per no tenir penalització, utilitzat en versió (v2) de la blockchain,
            "CRYPTONOTE_COIN_VERSION": Versió de CryptoNote,
            "CRYPTONOTE_DISPLAY_DECIMAL_POINT": Valor decimal en format atòmic,
            "CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW": Nombre de blocs per desbloquejar operacions de miners,
            "CRYPTONOTE_NAME": Nom de la criptomoneda, utilitzat per el directori on es guarda la informació,
            "CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX": Prefix de l'adreça de la cartera. Atès que les regles dels prefixos d'adreça no són típiques, podeu utilitzar un generador de prefixos,
            "DEFAULT_DUST_THRESHOLD": La quantiat per sota d'aquest valor es considera pols,
            "DIFFICULTY_CUT": Marca de temps del tall,
            "DIFFICULTY_LAG": Marca de temps per calcular la dificultat,
            "DIFFICULTY_TARGET": Objectiu o temps ideal entre blocs. Mesurat en segons,
            "EMISSION_SPEED_FACTOR": Constant que defineix la pendent de la corba d'emissió, necessari per calcular la recompensa del bloc,
            "EXPECTED_NUMBER_OF_BLOCKS_PER_DAY": Blocs generats aproximadament per dia,
            "GENESIS_BLOCK_REWARD": Quantitat referent al preminatge de la criptomoneda,
            "GENESIS_COINBASE_TX_HEX": Valor TX de la transacció inicial,
            "KILL_HEIGHT": Tancament de la cadena de blocs a l'alçada establerta,
            "MANDATORY_TRANSACTION": Només els blocs amb més de 1 transacció son valids,
            "MAX_BLOCK_SIZE_INITIAL": La mida del bloc inicial,
            "MINIMUM_FEE": Les transaccions amb menys d'aquesta tarifa no serian acceptades,
            "MONEY_SUPPLY": Quantitat total de criptomonedes,
            "P2P_DEFAULT_PORT": Port P2P utilitzat,
            "RPC_DEFAULT_PORT": Port RPC utilitzat,
            "SEED_NODES": IPs dels nodes principals
            "UPGRADE_HEIGHT_V2": Bloquejar l'alçada per moure's a blocs amb la versió principal 2. S'utilitza '1' per a noves cadenes de blocs,
            "UPGRADE_HEIGHT_V3": Bloquejar l'alçada per moure's a blocs amb la versió principal 3. S'utilitza '2' per a noves cadenes de blocs
        },
        "extensions": Extensions,
        "status": "OK"
    }

Exemple f_get_blockchain_settings (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"f_get_blockchain_settings","params":{},"jsonrpc":"2.0","id":"json_test"}'

Exemple f_get_blockchain_settings (sortida)

{"id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "base_coin": {
            "git": "https://github.com/amjuarez/bytecoin.git",
            "name": "bytecoin"
        },
        "core": {
            "BYTECOIN_NETWORK": "b11e5999-cbce-fe91-76f5-510abf30c885",
            "CHECKPOINTS": [],
            "CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE": 100000,
            "CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1": 10000,
            "CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2": 20000,
            "CRYPTONOTE_COIN_VERSION": 0,
            "CRYPTONOTE_DISPLAY_DECIMAL_POINT": 11,
            "CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW": 7,
            "CRYPTONOTE_NAME": "croat",
            "CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX": 70,
            "DEFAULT_DUST_THRESHOLD": 1000000,
            "DIFFICULTY_CUT": 60,
            "DIFFICULTY_LAG": 15,
            "DIFFICULTY_TARGET": 60,
            "EMISSION_SPEED_FACTOR": 20,
            "EXPECTED_NUMBER_OF_BLOCKS_PER_DAY": 1440,
            "GENESIS_BLOCK_REWARD": "1507011611056432600",
            "GENESIS_COINBASE_TX_HEX": "010701ff0001d8cba1abb6e2fef4140288ea25298cf01cbf265202303707116c16290882a0a3f47c60f7edd36a5f813c21011ba0f0ca3932e752111d5a4d8d03337cb44399d7e991bbc6148d018b35fd0a26",
            "KILL_HEIGHT": 0,
            "MANDATORY_TRANSACTION": 0,
            "MAX_BLOCK_SIZE_INITIAL": 100000,
            "MINIMUM_FEE": 1000000,
            "MONEY_SUPPLY": "10046744073709551615",
            "P2P_DEFAULT_PORT": 46347,
            "RPC_DEFAULT_PORT": 46348,
            "SEED_NODES": [
                "178.22.71.122:46347",
                "31.171.244.63:46347",
                "45.32.147.31:46347",
                "178.22.66.126:46347",
                "85.214.158.156:46347",
                "104.224.135.31:46347",
                "191.102.253.50:46347",
                "159.89.3.73:46347",
                "45.77.91.150:46347",
                "125.212.245.165:46347",
                "217.182.170.155:46347"
            ],
            "UPGRADE_HEIGHT_V2": 1,
            "UPGRADE_HEIGHT_V3": 2
        },
        "extensions": [
            "core/bytecoin.json",
            "print-genesis-tx.json",
            "genesis-block-reward.json"
        ],
        "status": "OK"
    }
}

  • getcurrencyid

Descripció: El mètode getcurrencyid retorna un valor únic referent a l’id de la moneda
Paràmetres: Cap
Resposta: string

Exemple getcurrencyid (entrada)

curl -X POST \
  http://127.0.0.1:46348/json_rpc \
  -H 'Content-Type: application/json-rpc' \
  -d '{"method":"getcurrencyid","params":{},"jsonrpc":"2.0","id":"json_test"}'

Exemple getcurrencyid (sortida)

{
    "id": "json_test",
    "jsonrpc": "2.0",
    "result": {
        "currency_id_blob": "8f8d0e094cb16c930739cca7e53e67e8be229e77a097ad13aa88db8df8f43091"
    }
}