Skip to content

Instantly share code, notes, and snippets.

@jtgrassie
Last active December 28, 2018 06:51
Show Gist options
  • Save jtgrassie/b466123d8a1eb9a62ca99a943809bba7 to your computer and use it in GitHub Desktop.
Save jtgrassie/b466123d8a1eb9a62ca99a943809bba7 to your computer and use it in GitHub Desktop.
Example of Monero's /get_o_indexes.bin RPC in Python
import requests
import struct
def get_o_indexes():
tx_hex = "942eaeb8ba05bd13e8d7b85f1599b52a808263419e680d2d1e32ed2f58f6cb78"
tx_bin_len = 32
# Portable storage signature and version
signature = 0x0111010101010201
version = 1
# Signature and version
req_data = struct.pack("> Q B", signature, version)
# Entry count, entry name length, entry name
req_data += struct.pack("< B B 4s", 1 << 2, 4, "txid")
# Entry value type (here a char array), entry value length (as varint)
req_data += struct.pack("< B B", 10, tx_bin_len << 2)
# Entry value data
req_data += bytearray.fromhex(tx_hex)
print
print "Calling /get_o_indexes.bin with:"
print " txid", ":", tx_hex
print
res = requests.post('http://localhost:18081/get_o_indexes.bin', data=req_data)
if res.status_code != 200:
print "Response status code:", res.status_code
return
# Everything that follows is a crude parsing of the response.
print "Parsed response:"
# First read & check the signatures and versions match...
buf = buffer(res.content)
offset = 0
res_signature, res_version = struct.unpack_from("> Q B", buf, offset)
offset = 10
if res_signature != signature:
print " Signature incorrect. Aborting."
return
if res_version != version:
print " Version incorrect. Aborting."
return
# Now read and parse each response field...
while offset < len(res.content):
field_len, = struct.unpack_from("< B", buf, offset)
offset += 1
field_name, = struct.unpack_from(str(field_len)+"s", buf, offset)
offset += field_len
field_type, = struct.unpack_from("< B", buf, offset)
offset += 1
if field_type == 0x85: # uint64_t array
arr_len, = struct.unpack_from("< B", buf, offset)
offset += 1
arr_len = arr_len >> 2
items = struct.unpack_from("< "+str(arr_len)+"Q", buf, offset)
offset += arr_len * 8
print " ", field_name, ":", items
elif field_type == 0x0A: # char array
str_len, = struct.unpack_from("< B", buf, offset)
offset += 1
str_len = str_len >> 2 # Being lazy as not checking with the mask!!!
item, = struct.unpack_from(str(str_len)+"s", buf, offset)
offset += str_len
print " ", field_name, ":", item
elif field_type == 0x0B: # bool
item, = struct.unpack_from("< ?", buf, offset)
offset += 1
print " ", field_name, ":", item
else:
print " Field type", hex(field_type), "not yet implemented. Aborting."
break
if __name__ == "__main__":
get_o_indexes()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment