Last active
June 11, 2023 09:01
-
-
Save NicolasFlamel1/56becb6beb5c9cdc0f2f1d457f379f7d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This demonstrates how to use the secp256k1-zkp-mw Python module, https://github.com/grinventions/secp256k1-zkp-mw, to find all the unspent Grin outputs belonging to a wallet. This code lacks any error checking. A wallet's rewind hash can be obtained by running the command `grin-wallet rewind_hash` with the Grin CLI wallet, https://github.com/mimblewimble/grin-wallet. | |
# Imports | |
from secp256k1_zkp_mw import * | |
from hashlib import blake2b | |
import requests | |
# Constants | |
# Rewind hash | |
REWIND_HASH = bytes.fromhex('99d92c1264de3edab618eeeb024533447c30c4d6549d70efc745fe385bd2862b') | |
# Server | |
SERVER = 'https://grinnode.live:3413' | |
# Functions | |
# Format number | |
def formatNumber(number): | |
# Return formatted number | |
return '{:.9f}'.format(number / 1E9).rstrip('0').rstrip('.') | |
# Main function | |
# Create context | |
context = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN) | |
# Get the tip height from the node | |
tipHeight = requests.post(SERVER + '/v2/foreign', json = { | |
'jsonrpc': '2.0', | |
'id': 1, | |
'method': 'get_tip', | |
'params': [] | |
}).json()['result']['Ok']['height'] | |
# Display start message | |
print('Scanning up to height %d for unspent outputs belonging to the wallet with the rewind hash %s. This may take a while.' % (tipHeight, REWIND_HASH.hex())) | |
# Get the PMMR indices from the genesis block to the tip height from the node | |
pmmrIndices = requests.post(SERVER + '/v2/foreign', json = { | |
'jsonrpc': '2.0', | |
'id': 1, | |
'method': 'get_pmmr_indices', | |
'params': [ | |
0, | |
tipHeight | |
] | |
}).json()['result']['Ok'] | |
# Get start and end indices from the PMMR indices | |
startIndex = pmmrIndices['last_retrieved_index'] | |
endIndex = pmmrIndices['highest_index'] | |
# Go through all unspent outputs in the PMMR indices range | |
while True: | |
# Get the next group of unspent outputs from the node | |
unspentOutputs = requests.post(SERVER + '/v2/foreign', json = { | |
'jsonrpc': '2.0', | |
'id': 1, | |
'method': 'get_unspent_outputs', | |
'params': [ | |
startIndex, | |
endIndex, | |
1000, | |
True | |
] | |
}).json()['result']['Ok'] | |
# Go through all unspent outputs in the group | |
for unspentOutput in unspentOutputs['outputs']: | |
# Get commit and proof from the unspent output | |
commit = bytes.fromhex(unspentOutput['commit']) | |
proof = bytes.fromhex(unspentOutput['proof']) | |
# Get rewind nonce for the commit | |
rewindNonce = blake2b(REWIND_HASH, digest_size = 32, key = commit).digest() | |
# Check if the unspent output belongs to the wallet | |
internalCommit = secp256k1_pedersen_commitment_parse(context, commit) | |
outputData = secp256k1_bulletproof_rangeproof_rewind(context, proof, 0, internalCommit, secp256k1_generator_const_h, rewindNonce, None) | |
if outputData is not None: | |
# Get amount from the output data | |
amount = outputData[0] | |
# Display unspent output found message | |
print('Found an unspent output with %s Grin at height %d.' % (formatNumber(amount), unspentOutput['block_height'])) | |
# Check if no more unspent outputs exist in the range | |
if unspentOutputs['highest_index'] <= unspentOutputs['last_retrieved_index']: | |
# Break | |
break | |
# Update start index | |
startIndex = unspentOutputs['last_retrieved_index'] + 1 | |
# Display end message | |
print('Done scanning for unspent outputs.') | |
# Destroy the context | |
secp256k1_context_destroy(context) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment