def get_dst_addr(say, rpc): """Generate an address and retrieve blinding key for it""" # Note that we could generate our own keys, and make # addresses from them, and then derive the blinding keys, # but then we would have to decide how to store the keys # for the user to be able to do own exploration # after example finishes working. We choose the easiest path. # # Note that if we have master blinding key # (Elements will include master blinding key in wallet dump # in future versions), we could derive the blinding key # from the master key and the address, with this code: # addr.to_scriptPubKey().derive_blinding_key(blinding_derivation_key) # derive_blinding_key() follows the logic of blinding key # derivation in Elements Core source. if say: say('Generating new address and retrieving blinding key for it') addr_str = rpc.getnewaddress() # Retrieve the blinding key blinding_key = CCoinKey.from_secret_bytes(x(rpc.dumpblindingkey(addr_str))) return CCoinAddress(addr_str), blinding_key
f = sys.argv[1] #with open(sys.argv[1]) as f: # We could use CTransaction here, but if we want to # use mypy to do static checking, we need to use the elements-specific # classes. mypy does cannot know about dynamic class dispatch. #tx = CElementsTransaction.deserialize(x(f.readline().rstrip())) [16/1870] tx = CElementsTransaction.deserialize(x(f)) # Read in the blinding key, expected to be in WIF format. f = sys.argv[2] #with open(sys.argv[2]) as f: #bkey = CCoinKey.from_secret_bytes(x(f.readline().rstrip())) bkey = CCoinKey.from_secret_bytes(x(f)) # Iterate through transaction ouptputs, and unblind what we can. print("") for n, vout in enumerate(tx.vout): # Note that nValue of vout in Elements is not a simple int, # but CConfidentialValue, which can either be explicit, and can be # converted to satoshis with to_amount(), or it can be blinded, in # which case you need to unblind the output to know its value. if vout.nValue.is_explicit(): # The output is not blinded, we can access the values right away assert vout.nAsset.is_explicit(), "unblinding just the asset is not supported" if vout.is_fee(): print("vout {}: fee".format(n)) else:
sys.exit(-1) # Switch the chain parameters to Elements select_chain_params('elements') # Read in and decode the blinded transaction. # expected to be hex-encoded as one line. with open(sys.argv[1]) as f: # We could use CTransaction here, but if we want to # use mypy to do static checking, we need to use the elements-specific # classes. mypy does cannot know about dynamic class dispatch. tx = CElementsTransaction.deserialize(x(f.readline().rstrip())) # Read in the blinding key, expected to be in WIF format. with open(sys.argv[2]) as f: bkey = CCoinKey.from_secret_bytes(x(f.readline().rstrip())) # Iterate through transaction ouptputs, and unblind what we can. print("") for n, vout in enumerate(tx.vout): # Note that nValue of vout in Elements is not a simple int, # but CConfidentialValue, which can either be explicit, and can be # converted to satoshis with to_amount(), or it can be blinded, in # which case you need to unblind the output to know its value. if vout.nValue.is_explicit(): # The output is not blinded, we can access the values right away assert vout.nAsset.is_explicit( ), "unblinding just the asset is not supported" if vout.is_fee(): print("vout {}: fee".format(n)) else:
# Read in and decode the blinded transaction. # expected to be hex-encoded as one line. with open(sys.argv[1]) as f: # We could use CTransaction here, but if we want to # use mypy to do static checking, we need to use the elements-specific # classes. mypy does cannot know about dynamic class dispatch. input_tx = CElementsTransaction.deserialize(x(f.readline().rstrip())) # Read in the key, expected to be in WIF format. with open(sys.argv[2]) as f: key = CCoinKey(f.readline().rstrip()) # Read in the unblinding key, expected to be in HEX format. with open(sys.argv[3]) as f: bkey = CCoinKey.from_secret_bytes(x(f.readline().rstrip())) dst_addr = CElementsAddress(sys.argv[4]) # Construct P2SH_P2WPKH address from the loaded key spk = CScript([0, Hash160(key.pub)]).to_p2sh_scriptPubKey() src_addr = P2SHCoinAddress.from_scriptPubKey(spk) sys.stderr.write( '\nSearching for ouptut with address {}\n'.format(src_addr)) utxo = None fee_asset = None # Search for output in the transaction that spends to the address that # we have. We are going to spend the first output that we find. for in_n, in_vout in enumerate(input_tx.vout):
elif args.verbosity >= 1: logging.root.setLevel(logging.DEBUG) elif args.verbosity == -1: logging.root.setLevel(logging.WARNING) elif args.verbosity <= -2: logging.root.setLevel(logging.ERROR) if args.testnet: bitcointx.select_chain_params('bitcoin/testnet') elif args.regtest: bitcointx.select_chain_params('bitcoin/regtest') rpc = bitcointx.rpc.RPCCaller(allow_default_conf=True) if args.privkey is None: args.privkey = CCoinKey.from_secret_bytes(os.urandom(32)) else: args.privkey = CCoinKey(args.privkey) logging.info('Using keypair %s %s' % (b2x(args.privkey.pub), args.privkey)) # Turn the text file into padded lines if args.fd is sys.stdin: # work around a bug where even though we specified binary encoding we get # the sys.stdin instead. args.fd = sys.stdin.buffer raw_padded_lines = [ b'\x00' + line.rstrip().ljust(args.min_len) + b'\x00' for line in args.fd.readlines() ]