def process_receive_entry(sqlcur, key, value): # blocks.cpp, deserialize_block(stream, type), rai::receive_block members previous_block = value[:32] source_block = value[32:64] signature = value[64:128] work = unpack('<Q', value[128:136])[0] successor = value[136:168] assert len(value[168:]) == 0 """ print('Receive block %s' % bin2hex(key)) print('... previous block %s' % bin2hex(previous_block)) print('... source block %s' % bin2hex(source_block)) print('... signature %s' % bin2hex(signature)) print('... work %08x' % work) print('... successor %s' % bin2hex(successor)) """ block_id = get_block_id(key) # XXX _id hash = bin2hex(key) previous_id = get_block_id(previous_block) source_id = get_block_id(source_block) signature = bin2hex(signature) work = '%08x' % work successor_id = get_block_id(successor) sqlcur.execute( 'insert into blocks (id, hash, type, previous, source, next) values (?,?,?,?,?,?)', (block_id, hash, 'receive', previous_id, source_id, successor_id)) sqlcur.execute( 'insert into block_validation (id, signature, work) values (?,?,?)', (block_id, signature, work))
def process_send_entry(sqlcur, key, value): # blocks.cpp, deserialize_block(stream, type), rai::send_block members previous_block = value[:32] destination = value[32:64] balance = value[64:80] signature = value[80:144] work = unpack('<Q', value[144:152])[0] successor = value[152:184] assert len(value[184:]) == 0 """ print('Send block %s' % bin2hex(key)) print('... previous block %s' % bin2hex(previous_block)) print('... destination %s (%s)' % (destination, encode_account(destination))) print('... balance %s (%.6f Mxrb)' % (bin2hex(balance), bin2balance_mxrb(balance))) print('... signature %s' % bin2hex(signature)) print('... work %08x' % work) print('... successor %s' % bin2hex(successor)) """ block_id = get_block_id(key) balance_mxrb = bin2balance_mxrb(balance) balance_raw = bin2balance_raw(balance) hash = bin2hex(key) previous_id = get_block_id(previous_block) destination_id = get_account_id(encode_account(destination)) signature = bin2hex(signature) work = '%08x' % work successor_id = get_block_id(successor) # Note that we store balance_raw (a Python long) as a string sqlcur.execute( 'insert into blocks (id, hash, type, previous, destination, balance, balance_raw, next) values (?,?,?,?,?,?,?,?)', (block_id, hash, 'send', previous_id, destination_id, balance_mxrb, str(balance_raw), successor_id)) sqlcur.execute( 'insert into block_validation (id, signature, work) values (?,?,?)', (block_id, signature, work))
def get_block_id(blockhash): # XXX this takes a bytes object, while get_account_id takes a string :-/ if bin2hex( blockhash ) == '0000000000000000000000000000000000000000000000000000000000000000': # Used in the LMDB database to indicate a null block "pointer" return None if bin2hex(blockhash) == GENESIS_PUBLIC_KEY: # Source block of the genesis open block does not exist return None global next_block_id try: return block_ids[blockhash] except KeyError: block_ids[blockhash] = next_block_id next_block_id += 1 return next_block_id - 1
def process_change_entry(sqlcur, key, value): # blocks.cpp, deserialize_block(stream, type), rai::change_block members previous_block = value[:32] representative = value[32:64] signature = value[64:128] work = unpack('<Q', value[128:136])[0] successor = value[136:168] assert len(value[168:]) == 0 """ print('Change block %s' % bin2hex(key)) print('... previous block %s' % bin2hex(previous_block)) print('... representative %s (%s)' % (bin2hex(representative), encode_account(representative))) print('... signature %s' % bin2hex(signature)) print('... work %08x' % work) print('... successor %s' % bin2hex(successor)) """ block_id = get_block_id(key) hash = bin2hex(key) previous_id = get_block_id(previous_block) representative_id = get_account_id(encode_account(representative)) signature = bin2hex(signature) work = '%08x' % work successor_id = get_block_id(successor) sqlcur.execute( 'insert into blocks (id, hash, type, previous, representative, next) values (?,?,?,?,?,?)', (block_id, hash, 'change', previous_id, representative_id, successor_id)) sqlcur.execute( 'insert into block_validation (id, signature, work) values (?,?,?)', (block_id, signature, work))
def process_open_entry(sqlcur, key, value): # blocks.cpp, deserialize_block(stream, type), rai::open_block members """ Special case: open block of the genesis account (991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948): { "type": "open", "source": "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA", "representative": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "account": "xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3", "work": "62f05417dd3fb691", "signature": "9F0C933C8ADE004D808EA1985FA746A7E95BA2A38F867640F53EC8F180BDFE9E2C1268DEAD7C2664F356E37ABA362BC58E46DBA03E523A7B5A19E4B6EB12BB02" } See rai/secure.cpp for this block. The source block does not exist! Receive 340,282,366.920938 XRB Where does the genesis balance come from? Holy crap, from ledger_constants::genesis_amount() in rai/secure.cpp: genesis_amount (std::numeric_limits<rai::uint128_t>::max ()) So, the initial amount available is 2**128-1 = 340282366920938463463374607431768211455 raw But why the non-existent source block? Ah, the source "block" is actually the public key of the Genesis account. char const * live_public_key_data = "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA"; // xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3 """ source_block = value[:32] representative = value[32:64] account = value[64:96] signature = value[96:160] work = unpack('<Q', value[160:168])[0] successor = value[168:200] assert len(value[200:]) == 0 """ print('Open block %s' % bin2hex(key)) print('... source block %s' % bin2hex(source_block)) print('... representative %s (%s)' % (bin2hex(representative), encode_account(representative))) print('... account %s (%s)' % (bin2hex(account), encode_account(account))) print('... signature %s' % bin2hex(signature)) print('... work %08x' % work) print('... successor %s' % bin2hex(successor)) """ block_id = get_block_id(key) hash = bin2hex(key) source_id = get_block_id(source_block) representative_id = get_account_id(encode_account(representative)) account_id = get_account_id(encode_account(account)) signature = bin2hex(signature) work = '%08x' % work successor_id = get_block_id(successor) sqlcur.execute( 'insert into blocks (id, hash, type, source, representative, account, next) values (?,?,?,?,?,?,?)', (block_id, hash, 'open', source_id, representative_id, account_id, successor_id)) sqlcur.execute( 'insert into block_validation (id, signature, work) values (?,?,?)', (block_id, signature, work))
aes = AES.new(derived_key, AES.MODE_CTR, counter=counter) wallet_key = aes.decrypt(encrypted_wallet_key) #print(bin2hex(wallet_key)) # Password check: # - Encrypt zeros with the (decrypted) wallet key # - Check against stored value # - Also uses only the first half of the salt counter = Counter.new(128, initial_value=initial_counter_value) aes = AES.new(wallet_key, AES.MODE_CTR, counter=counter) result = aes.encrypt('\x00' * 32) result = bin2hex(result).upper() check = wallet[KEY_CHECK_VALUE] if result != check: print(result) print(check) print('PASSWORD IS INCORRECT') sys.exit(-1) # Get encrypted seed for deterministic key generation # (i.e. THE wallet seed as entered in the Nano wallet) and decrypt it. # Note: uses only the first half of the salt for the CTR mode counter = Counter.new(128, initial_value=initial_counter_value) aes = AES.new(wallet_key, AES.MODE_CTR, counter=counter)