Last active
June 6, 2021 10:55
-
-
Save toysrtommy/75ac3d0ecf314942681c0a0fbdfabfa5 to your computer and use it in GitHub Desktop.
IC: Creating a new neuron (python)
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
from hashlib import sha224,sha256 | |
import binascii | |
import re | |
import os | |
import base64 | |
import math | |
import argparse | |
import sys | |
import subprocess | |
import zlib | |
CA_NNS = "rrkah-fqaaa-aaaaa-aaaaq-cai" | |
CMD_CALL= "dfx canister --network=https://ic0.app --no-wallet call" | |
CMD_CALLQ= "dfx canister --network=https://ic0.app --no-wallet call --query" | |
CMD_BROADCAST = "dfx canister --network=https://ic0.app --no-wallet send {}" | |
CMD_BROADCAST_Q = "dfx canister --network=https://ic0.app --no-wallet send {}" | |
CMD_REFRESH_NEURON="%s %s claim_or_refresh_neuron_from_account \"(record {{controller=principal \\\"{}\\\"; memo={}:nat64}})\"" % (CMD_CALL, CA_NNS) | |
CMD_TRANSFER= "dfx ledger --network https://ic0.app transfer {} --amount {} --memo {}" | |
## main method for staking a new neuron | |
def cmd_stakeneuron(amount): | |
# Get current principal ID | |
principal = get_principal() | |
# Generate a neuron account id (a subaccount of governance canister) | |
dest,memo = nns_subaccount(principal) | |
dest = dest[2:] | |
# Transfer the specified amount ICP to the new neuron | |
transfer = CMD_TRANSFER.format(dest, amount, memo) | |
print(transfer) | |
# Notify/refresh the NNS canister on the transfer | |
refresh = CMD_REFRESH_NEURON.format(principal, memo) | |
print(refresh) | |
try_cmd(transfer, 2) | |
try_cmd(refresh, 2) | |
CMD_GET_PRINCIPAL = "dfx identity get-principal" | |
def get_principal(): | |
p = try_cmd(CMD_GET_PRINCIPAL,0).stdout | |
p = p.decode("ascii")[:63] | |
return p | |
# Generate subaccount based on principal | |
def nns_subaccount(principal_str): | |
nounce = os.urandom(8) | |
nounce_s = str(int.from_bytes(nounce, "big")) | |
print("nounce bytes: " + nounce_s) | |
# print(principal_str) | |
principal = principal_to_blob(principal_str) | |
padding = b'neuron-stake' | |
subaccount = sha256(b'\x0c' + padding + principal + nounce).hexdigest() | |
subaccount = bytearray.fromhex(subaccount) | |
# print("subaccount: " + bytes_to_string(subaccount)) | |
nns_accountid = principal_to_accountid(principal_to_blob_str(CA_NNS), subaccount) | |
checksum = hex(zlib.crc32(bytes.fromhex(nns_accountid)) & 0xffffffff) | |
nns_accountid = checksum+nns_accountid | |
return nns_accountid, nounce_s | |
def try_cmd(cmd, retries, input=None): | |
res = subprocess.run(cmd, shell=True,input=input,capture_output=True) | |
if (res.returncode != 0): | |
print("cmd execution Error! ") | |
print(res) | |
if (retries >0): | |
time.sleep(2) | |
print(" ... retrying ") | |
return try_cmd(cmd, retries-1) | |
return res | |
def principal_to_blob_str(principal): | |
pid = principal_to_blob(principal) | |
p = "".join('{:02x}'.format(x) for x in pid) | |
return p | |
def principal_to_blob(principal): | |
principal = principal.replace("-","") | |
# print("extra: " + str(len(str.encode(principal)) % 8)) | |
# Pad as neccessary for base32 decoding | |
pad = 8 - len(str.encode(principal)) % 8 | |
principal += "=" *pad | |
# print(principal) | |
principal = base64.b32decode(principal, True) | |
principal = principal[4:len(principal)] | |
p = "".join('{:02d} '.format(x) for x in principal) | |
# print("blob: " + p) | |
return principal | |
def bytes_to_string(b): | |
return("".join('{:02d} '.format(x) for x in b)) | |
def principal_to_accountid(principal, subaccount=None): | |
# print("decoding principal ... " + principal) | |
p=bytes.fromhex(principal) | |
pad = subaccount | |
# print("decimal subaccount array (%s): " % len(subaccount) + bytes_to_string(subaccount) ) | |
if (not subaccount): | |
pad = b'\x00'*32 | |
s = sha224(b'\x0aaccount-id'+p+pad) | |
return s.hexdigest() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment