def parse_input_txs(input_tx_files): input_txs_map = {} for input_tx_file in input_tx_files or []: input_tx = parse_tx_file(input_tx_file) txid = wally.sha256d(wally.tx_to_bytes(input_tx, 0)) input_txs_map[bytes(txid)] = input_tx return input_txs_map
def main(): parser = argparse.ArgumentParser(description="Verify Elements Commitments") parser.add_argument("--tx", type=argparse.FileType("r"), required=True) parser.add_argument("--blinded", type=argparse.FileType("r"), required=True) parser.add_argument("--input-txs", type=argparse.FileType("r"), nargs="+") args = parser.parse_args() tx = parse_tx_file(args.tx) inputs_unblinded, outputs_unblinded = parse_blinded_file(args.blinded) input_txs_map = parse_input_txs(args.input_txs) ret = { "txid": b2h_rev(wally.sha256d(wally.tx_to_bytes(tx, 0))), "inputs": [], "outputs": [], } for inp_idx in range(wally.tx_get_num_inputs(tx)): input_unblinded = inputs_unblinded.get(inp_idx) if not input_unblinded: continue prev_txid = wally.tx_get_input_txhash(tx, inp_idx) prev_vout = wally.tx_get_input_index(tx, inp_idx) prev_tx = input_txs_map.get(bytes(prev_txid)) if not prev_tx: continue asset_commitment_bin = wally.tx_get_output_asset(prev_tx, prev_vout) amount_commitment_bin = wally.tx_get_output_value(prev_tx, prev_vout) if asset_commitment_bin != input_unblinded["asset_commitment_bin"]: continue i = {"vin": inp_idx} # TODO: fill also if unblinded if input_unblinded.get("asset_id_hex"): i["asset"] = input_unblinded["asset_id_hex"] if amount_commitment_bin == input_unblinded["amount_commitment_bin"]: i["satoshi"] = input_unblinded["amount_satoshi"] ret["inputs"].append(i) for out_idx in range(wally.tx_get_num_outputs(tx)): output_unblinded = outputs_unblinded.get(out_idx) if not output_unblinded: continue asset_commitment_bin = wally.tx_get_output_asset(tx, out_idx) amount_commitment_bin = wally.tx_get_output_value(tx, out_idx) if asset_commitment_bin != output_unblinded["asset_commitment_bin"]: continue o = {"vout": out_idx} # TODO: fill also if unblinded if output_unblinded.get("asset_id_hex"): o["asset"] = output_unblinded["asset_id_hex"] if amount_commitment_bin == output_unblinded["amount_commitment_bin"]: o["satoshi"] = output_unblinded["amount_satoshi"] ret["outputs"].append(o) print(json.dumps(ret, indent=2))
def check_contract(prev_tx, prev_vout, contract_hash, asset): a = wally.hex_from_bytes(wally.hex_to_bytes(prev_tx)[::-1])+wally.hex_from_bytes(struct.pack('<L', int(prev_vout))) a = wally.hex_from_bytes(wally.sha256d(wally.hex_to_bytes(a))) b = a + contract_hash merkle = wally.hex_from_bytes(wally.sha256_midstate(wally.hex_to_bytes(b))) c = merkle + '0000000000000000000000000000000000000000000000000000000000000000' asset_id = wally.hex_from_bytes(wally.sha256_midstate(wally.hex_to_bytes(c))[::-1]) return(asset_id == asset)
def tx_segwit_hash(tx, i, script, value): # BIP143: # 1. nVersion tx_bin = struct.pack("<L", 1) # 2. hashPrevouts to_hash = b"" for inp in tx.txs_in: to_hash += inp.previous_hash to_hash += struct.pack("<L", inp.previous_index) tx_bin += sha256d(to_hash) # 3. hashSequence to_hash = b"".join(struct.pack("<L", inp.sequence) for inp in tx.txs_in) tx_bin += sha256d(to_hash) # 4. transaction id and output index of the output spent by this input tx_bin += tx.txs_in[i].previous_hash tx_bin += struct.pack("<L", tx.txs_in[i].previous_index) # 5. subscript of the input tx_bin += bc_int(len(script)) + script # 6. value of the output spent by this input tx_bin += struct.pack("<Q", value) # 7. nSequence of the input tx_bin += struct.pack("<L", tx.txs_in[i].sequence) # 8. hashOutputs to_hash = b"" for out in tx.txs_out: to_hash += struct.pack('<Q', out.coin_value) to_hash += bc_int(len(out.script)) + out.script tx_bin += sha256d(to_hash) # 9. nLockTime tx_bin += struct.pack("<L", tx.lock_time) # 10. hashType tx_bin += struct.pack("<L", 0x41) # BCASH return sha256d(tx_bin)
def _decrypt_mnemonic(mnemonic, password): """Decrypt a 27 word encrypted mnemonic to a 24 word mnemonic""" mnemonic = ' '.join(mnemonic.split()) entropy = bytearray(wally.BIP39_ENTROPY_LEN_288) assert wally.bip39_mnemonic_to_bytes(None, mnemonic, entropy) == len(entropy) salt, encrypted = entropy[32:], entropy[:32] derived = bytearray(64) wally.scrypt(password.encode('utf-8'), salt, 16384, 8, 8, derived) key, decrypted = derived[32:], bytearray(32) wally.aes(key, encrypted, wally.AES_FLAG_DECRYPT, decrypted) for i in range(len(decrypted)): decrypted[i] ^= derived[i] if wally.sha256d(decrypted)[:4] != salt: raise exceptions.InvalidMnemonicOrPasswordError('Incorrect password') return wally.bip39_mnemonic_from_bytes(None, decrypted)
def get_txhash_bin(tx): return bytes(wally.sha256d(wally.tx_to_bytes(tx, 0)))
'name': name, 'ticker': ticker, 'precision': precision, 'entity': { 'domain': domain }, 'issuer_pubkey': issuer_pubkey, 'version': version }, separators=(',', ':'), sort_keys=True) contract_hash = wally.hex_from_bytes(wally.sha256(contract.encode('ascii'))) a = wally.hex_from_bytes( wally.hex_to_bytes(prev_tx)[::-1]) + wally.hex_from_bytes( struct.pack('<L', int(prev_vout))) a = wally.hex_from_bytes(wally.sha256d(wally.hex_to_bytes(a))) b = a + contract_hash merkle = wally.hex_from_bytes(wally.sha256_midstate(wally.hex_to_bytes(b))) c = merkle + '0000000000000000000000000000000000000000000000000000000000000000' merkle = wally.hex_from_bytes( wally.sha256_midstate(wally.hex_to_bytes(c))[::-1]) res['asset_id'] = merkle res['contract'] = contract res['contract_hash'] = contract_hash # Create the rawissuance transaction contract_hash_rev = wally.hex_from_bytes( wally.hex_to_bytes(contract_hash)[::-1]) rawissue = host_1.call('rawissueasset', funded['hex'], [{ 'asset_amount': amount,
def sign_tx(self, details: Dict) -> Dict: txhex = details['transaction']['transaction'] signing_inputs = details['signing_inputs'] use_ae_protocol = details['use_ae_protocol'] transaction_outputs = details['transaction_outputs'] logging.debug('sign liquid txn with %d inputs and %d outputs', len(signing_inputs), len(transaction_outputs)) def _map_input(input: Dict) -> Dict: is_segwit = input['address_type'] in ['p2wsh', 'csv', 'p2sh-p2wpkh', 'p2wpkh'] mapped = { 'is_witness': is_segwit, 'path': input['user_path'], 'value_commitment': bytes.fromhex(input['commitment']), 'script': bytes.fromhex(input['prevout_script'])} # Additional fields to pass through if using the Anti-Exfil protocol if use_ae_protocol: mapped['ae_host_commitment'] = bytes.fromhex(input['ae_host_commitment']) mapped['ae_host_entropy'] = bytes.fromhex(input['ae_host_entropy']) return mapped # Get inputs and change outputs in form Jade expects jade_inputs = list(map(_map_input, signing_inputs)) change = list(map(self._map_change_output, transaction_outputs)) # Calculate the hash-prevout from the inputs values, abfs, vbfs, input_prevouts = [], [], [], [] for input in signing_inputs: # Get values, abfs and vbfs from inputs (needed to compute the final output vbf) values.append(input['satoshi']) abfs.append(bytes.fromhex(input['assetblinder'])[::-1]) vbfs.append(bytes.fromhex(input['amountblinder'])[::-1]) # Get the input prevout txid and index for hashing later input_prevouts.append(bytes.fromhex(input['txhash'])[::-1]) input_prevouts.append(input['pt_idx'].to_bytes(4, byteorder='little')) hash_prevouts = bytes(wally.sha256d(b''.join(input_prevouts))) # Get the trusted commitments from Jade idx, trusted_commitments = 0, [] blinded_outputs = transaction_outputs[:-1] # Assume last output is fee for output in blinded_outputs[:-1]: # Not the last blinded output as we calculate the vbf for that commitments = self._get_trusted_commitments(idx, output, hash_prevouts, None) trusted_commitments.append(commitments) values.append(output['satoshi']) abfs.append(commitments['abf']) vbfs.append(commitments['vbf']) idx += 1 # Calculate the final vbf values.append(blinded_outputs[idx]['satoshi']) finalAbf = self.jade.get_blinding_factor(hash_prevouts, idx, 'ASSET') abfs.append(finalAbf) final_vbf = bytes(wally.asset_final_vbf(values, len(signing_inputs), b''.join(abfs), b''.join(vbfs))) # Get the final trusted commitments from Jade (with the calculated vbf) commitments = self._get_trusted_commitments(idx, blinded_outputs[idx], hash_prevouts, final_vbf) trusted_commitments.append(commitments) # Add a 'null' commitment for the final (fee) output trusted_commitments.append(None) # Sign! txn = bytes.fromhex(txhex) signatures = self.jade.sign_liquid_tx(self.network, txn, jade_inputs, trusted_commitments, change, use_ae_protocol) assert len(signatures) == len(signing_inputs) result = {} if use_ae_protocol: # If using the Anti-Exfil protocol, the response is a list of # (signer_commitment, signature), so need to unzip the lists signer_commitments, signatures = zip(*signatures) signer_commitments = list(map(bytes.hex, signer_commitments)) result['signer_commitments'] = signer_commitments signatures = list(map(bytes.hex, signatures)) result['signatures'] = signatures # Poke the blinding factors into the results structure self._populate_result(trusted_commitments, result) logging.debug('resolving {}'.format(result)) return json.dumps(result)
def hash(self) -> bytes: """The transaction hash (differs from txid for witness transactions)""" return wally.sha256d(self.to_bytes(use_witness=True))
def txid(self) -> bytes: """The transaction id""" return wally.sha256d(self.to_bytes())
BITCOIN = wally.hex_to_bytes(BITCOIN)[::-1] wally.tx_add_elements_raw_output( output_tx, None, bytearray([0x01]) + BITCOIN, wally.tx_confidential_value_from_satoshi(fee), None, # nonce None, # surjection proof None, # range proof 0) # end-add_fee # start-sign vout = 0 prev_txid = wally.sha256d(wally.tx_to_bytes(tx, 0)) for vin, script_pubkey in zip(vouts_in, script_pubkeys_in): wally.tx_add_elements_raw_input( output_tx, prev_txid, vin, 0xffffffff, None, # scriptSig None, # witness None, # nonce None, # entropy None, # issuance amount None, # inflation keys None, # issuance amount rangeproof None, # inflation keys rangeproof