def check_sign(self, blinded_tx: CTransaction, signed_tx: CTransaction, bundle: Dict[str, Any]) -> None: tx_to_sign = blinded_tx.to_mutable() for n, vin in enumerate(tx_to_sign.vin): utxo = bundle['vin_utxo'][n] amount = -1 if utxo['amount'] == -1 else coins_to_satoshi( utxo['amount']) scriptPubKey = CScript(x(utxo['scriptPubKey'])) a = CCoinAddress(utxo['address']) if 'privkey' in utxo: privkey = CCoinKey(utxo['privkey']) assert isinstance(a, P2PKHCoinAddress),\ "only P2PKH is supported for single-sig" assert a == P2PKHElementsAddress.from_pubkey(privkey.pub) assert scriptPubKey == a.to_scriptPubKey() sighash = SignatureHash(scriptPubKey, tx_to_sign, n, SIGHASH_ALL, amount=amount, sigversion=SIGVERSION_BASE) sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) tx_to_sign.vin[n].scriptSig = CScript( [CScript(sig), CScript(privkey.pub)]) else: pk_list = [CCoinKey(pk) for pk in utxo['privkey_list']] redeem_script_data = [utxo['num_p2sh_participants']] redeem_script_data.extend([pk.pub for pk in pk_list]) redeem_script_data.extend([len(pk_list), OP_CHECKMULTISIG]) redeem_script = CScript(redeem_script_data) assert isinstance(a, P2SHCoinAddress),\ "only P2SH is supported for multi-sig." assert scriptPubKey == redeem_script.to_p2sh_scriptPubKey() assert a == P2SHElementsAddress.from_scriptPubKey( redeem_script.to_p2sh_scriptPubKey()) sighash = SignatureHash(redeem_script, tx_to_sign, n, SIGHASH_ALL, amount=amount, sigversion=SIGVERSION_BASE) sigs = [ pk.sign(sighash) + bytes([SIGHASH_ALL]) for pk in pk_list ] tx_to_sign.vin[n].scriptSig = CScript([b''] + sigs + [redeem_script]) VerifyScript(tx_to_sign.vin[n].scriptSig, scriptPubKey, tx_to_sign, n, amount=amount) self.assertEqual(tx_to_sign.serialize(), signed_tx.serialize())
def find_utxo_for_fee(say, die, rpc): """Find suitable utxo to pay the fee. Retrieve thekey to spend this utxo and add it to the returned dict.""" # Find utxo to use for fee. In our simple example, only Alice pays the fee. # To be on a safe side, include only transactions # that are confirmed (1 as 'minconf' argument of listunspent) # and safe to spend (False as 'include_unsafe' # argument of listunspent) say('Searching for utxo for fee asset') utxo_list = rpc.listunspent(1, 9999999, [], False, {'asset': fee_asset.to_hex()}) utxo_list.sort(key=lambda u: u['amount']) for utxo in utxo_list: # To not deal with possibility of dust outputs, # just require fee utxo to be big enough if coins_to_satoshi(utxo['amount']) >= FIXED_FEE_SATOSHI * 2: utxo['key'] = CCoinKey(rpc.dumpprivkey(utxo['address'])) if 'assetcommitment' not in utxo: # If UTXO is not blinded, Elements daemon will not # give us assetcommitment, so we need to generate it ourselves. asset = CAsset(lx(utxo['asset'])) utxo['assetcommitment'] = b2x(asset.to_commitment()) return utxo else: die('Cannot find utxo for fee that is >= {} satoshi'.format( FIXED_FEE_SATOSHI * 2))
def issue_asset(say, asset_amount, rpc): """Issue asset and return CAsset instance and utxo to spend""" say('Issuing my own new asset, amount: {}'.format(asset_amount)) # No reissuance, so we specify tokenamount as 0 issue = rpc.issueasset(asset_amount, 0) asset_str = issue['asset'] say('The asset is {}'.format(asset_str)) say('Getting unspent utxo for asset {}'.format(asset_str)) # There should be only one utxo for newly-issued asset, we can use # destructuring assignment to get the first element of resulting list. # Utxo should be unconfirmed yet, so we specify 0 for minconf and maxconf. (asset_utxo, ) = rpc.listunspent(0, 0, [], False, {'asset': asset_str}) say('Unspent utxo for asset {} is {}:{}'.format(asset_str, asset_utxo['txid'], asset_utxo['vout'])) say("Retrieving private key to spend UTXO (source address {})".format( asset_utxo['address'])) # Retrieve key to spend the UTXO and add it to asset_utxo dict asset_utxo['key'] = CCoinKey(rpc.dumpprivkey(asset_utxo['address'])) return asset_str, asset_utxo
def print_verbose(signature, key, msg): secret = CCoinKey(key) address = P2PKHCoinAddress.from_pubkey(secret.pub) message = BitcoinMessage(msg) print('Address: %s' % address) print('Message: %s' % msg) print('Signature: %s' % signature) print('Verified: %s' % VerifyMessage(address, message, signature)) print('\nTo verify using bitcoin core:') print('\n`bitcoin-cli verifymessage %s \'%s\' \'%s\'`\n' % (address, signature.decode('ascii'), msg))
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
def test(self) -> None: xpriv1 = CCoinExtKey( 'xprv9s21ZrQH143K4TFwadu5VoGfAChTWXUw49YyTWE8SRqC9ZC9AQpHspzgbAcScTmC4MURiMT7pmCbci5oKbWijJmARiUeRiLXYehCtsoVdYf' ) xpriv2 = CCoinExtKey( 'xprv9uZ4jKNZFfGEQTTunEuy2cLQMckzuy5saCmiKuxYJgHX5pGFCx3KQ8mTkSfuLNaWGNQ9LKCg5YzUihxoQv493ErnkcaS3q1udx9X8WZbwZc' ) priv1 = CCoinKey( 'L27zAtDgjDC34sG5ZSey1wvdZ9JyZsNnvZEwbbZYWUYXXQtgri5R') xpub1 = CCoinExtPubKey( 'xpub69b6hm71WMe1PGpgUmaDPkbxYoTzpmswX8KGeinv7SPRcKT22RdMM4416kqtEUuXqXCAi7oGx7tHwCRTd3JHatE3WX1Zms6Lgj5mrbFyuro' ) xpub1.assign_derivation_info( KeyDerivationInfo(xpub1.parent_fp, BIP32Path('m/0'))) pub1 = CPubKey( x('03b0fe9cfc88fed9fcecf9dcb7bb5c90dd1a4500f4cfc5c854ffc8e54d639d6bc5' )) kstore = KeyStore( external_privkey_lookup=(lambda key_id, dinfo: priv1 if key_id == priv1.pub.key_id else None), external_pubkey_lookup=(lambda key_id, dinfo: pub1 if key_id == pub1.key_id else None)) self.assertEqual(kstore.get_privkey(priv1.pub.key_id), priv1) self.assertEqual(kstore.get_pubkey(pub1.key_id), pub1) self.assertEqual(kstore.get_pubkey(priv1.pub.key_id), priv1.pub) kstore = KeyStore(xpriv1, priv1, xpub1, pub1, require_path_templates=False) self.assertEqual(kstore.get_privkey(priv1.pub.key_id), priv1) self.assertEqual(kstore.get_pubkey(priv1.pub.key_id), priv1.pub) self.assertEqual(kstore.get_pubkey(pub1.key_id), pub1) # check that no-derivation lookup for (priv, pub) of extended keys # does not return anything if derivation is not supplied, # but returns pubkey when empty path is supplied self.assertEqual(kstore.get_privkey(xpriv1.pub.key_id), None) self.assertEqual( kstore.get_privkey( xpriv1.pub.key_id, KeyDerivationInfo(xpriv1.fingerprint, BIP32Path("m"))), xpriv1.priv) self.assertEqual(kstore.get_pubkey(xpriv1.pub.key_id), None) self.assertEqual( kstore.get_pubkey( xpriv1.pub.key_id, KeyDerivationInfo(xpriv1.fingerprint, BIP32Path("m"))), xpriv1.pub) # can't find xpub1's pub without derivation self.assertEqual(kstore.get_pubkey(xpub1.pub.key_id), None) # can find with correct derivation info supplied self.assertEqual( kstore.get_pubkey( xpub1.pub.key_id, KeyDerivationInfo(xpub1.parent_fp, BIP32Path("m/0"))), xpub1.pub) # but not with incorrect derivation info self.assertEqual( kstore.get_pubkey( xpub1.pub.key_id, KeyDerivationInfo(xpub1.parent_fp, BIP32Path("m"))), None) # check longer derivations self.assertEqual( kstore.get_privkey(xpriv1.derive_path("0'/1'/2'").pub.key_id), None) self.assertEqual( kstore.get_privkey( xpriv1.derive_path("0'/1'/2'").pub.key_id, KeyDerivationInfo(xpriv1.fingerprint, BIP32Path("m/0'/1'/2'"))), xpriv1.derive_path("0'/1'/2'").priv) self.assertEqual( kstore.get_pubkey( xpriv1.derive_path("0'/1'/2'").pub.key_id, KeyDerivationInfo(xpriv1.fingerprint, BIP32Path("m/0'/1'/2'"))), xpriv1.derive_path("0'/1'/2'").pub) self.assertEqual( kstore.get_pubkey( xpub1.derive_path("0/1/2").pub.key_id, KeyDerivationInfo(xpub1.parent_fp, BIP32Path('m/0/0/1/2'))), xpub1.derive_path("0/1/2").pub) path = BIP32Path("0'/1'/2'") derived_xpub = xpriv2.derive_path(path).neuter() derived_pub = derived_xpub.derive_path('3/4/5').pub self.assertEqual(kstore.get_pubkey(derived_pub.key_id), None) kstore.add_key(derived_xpub) self.assertEqual( kstore.get_pubkey( derived_pub.key_id, KeyDerivationInfo(xpriv2.parent_fp, BIP32Path("m/0/0'/1'/2'/3/4/5"))), derived_pub) kstore.add_key(xpriv2) derived_pub = xpriv2.derive_path('3h/4h/5h').pub self.assertEqual( kstore.get_pubkey( derived_pub.key_id, KeyDerivationInfo(xpriv2.parent_fp, BIP32Path("m/0/3'/4'/5'"))), derived_pub) derived_priv = xpriv2.derive_path('3h/4h/5h').priv self.assertEqual( kstore.get_privkey( derived_priv.pub.key_id, KeyDerivationInfo(xpriv2.parent_fp, BIP32Path("m/0/3'/4'/5'"))), derived_priv) # check that .remove_key() works kstore.remove_key(xpriv1) kstore.remove_key(xpub1) kstore.remove_key(priv1) kstore.remove_key(pub1) self.assertEqual(kstore.get_privkey(priv1.pub.key_id), None) self.assertEqual(kstore.get_pubkey(pub1.key_id), None) self.assertEqual( kstore.get_privkey( xpriv1.derive_path("0'/1'/2'").pub.key_id, KeyDerivationInfo(xpriv1.fingerprint, BIP32Path("m/0'/1'/2'"))), None) self.assertEqual( kstore.get_pubkey(xpub1.derive_path("0/1/2").pub.key_id), None)
def test_path_template_enforcement(self) -> None: xpriv1 = CCoinExtKey( 'xprv9s21ZrQH143K4TFwadu5VoGfAChTWXUw49YyTWE8SRqC9ZC9AQpHspzgbAcScTmC4MURiMT7pmCbci5oKbWijJmARiUeRiLXYehCtsoVdYf' ) xpriv2 = CCoinExtKey( 'xprv9s21ZrQH143K3QgBvK4tkeHuvuWc6KETTTcgGQ4NmW7g16AtCPV4hZpujiimpLM9ivFPgsMdNNVuVUnDwChutxczNKYHzP1Mo5HuqG7CNYv' ) assert xpriv2.derivation_info assert len(xpriv2.derivation_info.path) == 0 priv1 = CCoinKey( 'L27zAtDgjDC34sG5ZSey1wvdZ9JyZsNnvZEwbbZYWUYXXQtgri5R') xpub1 = CCoinExtPubKey( 'xpub69b6hm71WMe1PGpgUmaDPkbxYoTzpmswX8KGeinv7SPRcKT22RdMM4416kqtEUuXqXCAi7oGx7tHwCRTd3JHatE3WX1Zms6Lgj5mrbFyuro' ) xpub2 = xpriv2.derive(333).neuter() xpub1.assign_derivation_info( KeyDerivationInfo(xpub1.parent_fp, BIP32Path('m/0'))) pub1 = CPubKey( x('03b0fe9cfc88fed9fcecf9dcb7bb5c90dd1a4500f4cfc5c854ffc8e54d639d6bc5' )) xpub3 = xpub1.derive(0) xpub3.assign_derivation_info( KeyDerivationInfo(x('abcdef10'), BIP32Path('m/0/0'))) # No error when require_path_templates is not set KeyStore(xpriv1, xpriv2, priv1, xpub1, pub1, require_path_templates=False) with self.assertRaisesRegex(ValueError, 'only make sense for extended keys'): KeyStore((priv1, BIP32PathTemplate(''))) # type: ignore with self.assertRaisesRegex(ValueError, 'only make sense for extended keys'): KeyStore((pub1, [BIP32PathTemplate('')])) # type: ignore with self.assertRaisesRegex(ValueError, 'path templates must be specified'): KeyStore(xpriv1) with self.assertRaisesRegex(ValueError, 'path templates must be specified'): KeyStore(xpub1) # same but via add_key ks = KeyStore() with self.assertRaisesRegex(ValueError, 'only make sense for extended keys'): ks.add_key((priv1, BIP32PathTemplate(''))) # type: ignore with self.assertRaisesRegex(ValueError, 'only make sense for extended keys'): ks.add_key((pub1, [BIP32PathTemplate('')])) # type: ignore with self.assertRaisesRegex(ValueError, 'path templates list is empty'): ks.add_key((pub1, [])) # type: ignore with self.assertRaisesRegex(ValueError, 'only make sense for extended keys'): ks.add_key((pub1, '')) # type: ignore with self.assertRaisesRegex(ValueError, 'index template format is not valid'): ks.add_key((xpub1, 'abc')) # type: ignore with self.assertRaisesRegex(TypeError, 'is expected to be an instance of '): ks.add_key((xpub1, [10])) # type: ignore with self.assertRaisesRegex(ValueError, 'path templates must be specified'): ks.add_key(xpriv1) with self.assertRaisesRegex(ValueError, 'path templates must be specified'): ks.add_key(xpub1) # No error when path templates are specified for extended keys ks = KeyStore( (xpriv1, BIP32PathTemplate('m')), (xpriv2, 'm/[44,49,84]h/0h/0h/[0-1]/*'), (xpub1, ''), # '' same as BIP32PathTemplate('') (xpub2, ['0/1', 'm/333/3/33']), (xpub3, BIP32PathTemplate('m/0/0/1')), priv1, pub1) self.assertEqual(ks.get_privkey(priv1.pub.key_id), priv1) self.assertEqual(ks.get_pubkey(pub1.key_id), pub1) # still can find non-extended priv even if derivation info is # specified, because there's exact match. self.assertEqual( ks.get_privkey(priv1.pub.key_id, KeyDerivationInfo(xpriv1.parent_fp, BIP32Path("m"))), priv1) self.assertEqual(ks.get_pubkey(pub1.key_id), pub1) # can't find without derivation specified self.assertEqual(ks.get_privkey(xpriv1.pub.key_id), None) # but can find with derivation specified self.assertEqual( ks.get_privkey( xpriv1.pub.key_id, KeyDerivationInfo(xpriv1.fingerprint, BIP32Path('m'))), xpriv1.priv) # can't find without derivation specified self.assertEqual(ks.get_pubkey(xpub1.pub.key_id), None) # can find with derivation specified self.assertEqual( ks.get_pubkey(xpub1.pub.key_id, KeyDerivationInfo(xpub1.parent_fp, BIP32Path('m/0'))), xpub1.pub) # exception when derivation goes beyond template with self.assertRaises(BIP32PathTemplateViolation): ks.get_pubkey( xpub1.derive(1).pub.key_id, KeyDerivationInfo(xpub1.parent_fp, BIP32Path('m/0/1'))) # success when template allows self.assertEqual( ks.get_pubkey( xpub3.derive(1).pub.key_id, KeyDerivationInfo(x('abcdef10'), BIP32Path('m/0/0/1'))), xpub3.derive(1).pub) # fails when template not allows with self.assertRaises(BIP32PathTemplateViolation): ks.get_pubkey( xpub3.derive(2).pub.key_id, KeyDerivationInfo(x('abcdef10'), BIP32Path('m/0/0/2'))) long_path = BIP32Path( "m/43435/646/5677/5892/58885/2774/9943/75532/8888") with self.assertRaises(BIP32PathTemplateViolation): ks.get_privkey( xpriv2.derive_path(long_path).pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, long_path)) with self.assertRaises(BIP32PathTemplateViolation): ks.get_privkey( xpriv2.derive_path("44'/0'/0'/3/25").pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/44h/0h/0h/3/25'))) with self.assertRaises(BIP32PathTemplateViolation): ks.get_privkey( xpriv2.derive_path("44'/0'/0'/0/1'").pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/44h/0h/0h/0/1h'))) self.assertEqual( ks.get_privkey( xpriv2.derive_path("44'/0'/0'/1/25").pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/44h/0h/0h/1/25'))), xpriv2.derive_path("44'/0'/0'/1/25").priv) with self.assertRaises(BIP32PathTemplateViolation): ks.get_pubkey( xpub2.derive_path('0').pub.key_id, KeyDerivationInfo(xpub2.parent_fp, BIP32Path('m/333/0'))) with self.assertRaises(BIP32PathTemplateViolation): ks.get_pubkey( xpub2.derive_path('3/34').pub.key_id, KeyDerivationInfo(xpub2.parent_fp, BIP32Path('m/333/3/34'))) self.assertEqual( ks.get_pubkey( xpub2.derive_path('3/33').pub.key_id, KeyDerivationInfo(xpub2.parent_fp, BIP32Path('m/333/3/33'))), xpub2.derive_path('3/33').pub) xpub49 = xpriv2.derive_path("m/49'/0'/0'/0").neuter() with self.assertRaisesRegex(ValueError, 'must specify full path'): ks = KeyStore( xpriv2, xpub49, default_path_template='[44,49,84]h/0h/0h/[0-1]/[0-50000]') ks = KeyStore( xpriv2, xpub49, default_path_template='m/[44,49,84]h/0h/0h/[0-1]/[0-50000]') with self.assertRaises(BIP32PathTemplateViolation): ks.get_privkey( xpriv2.derive_path(long_path).pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, long_path)) with self.assertRaises(BIP32PathTemplateViolation): ks.get_privkey( xpriv2.derive_path("44'/0'/0'/1/50001").pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/44h/0h/0h/1/50001'))) self.assertEqual( ks.get_privkey( xpriv2.derive_path("44'/0'/0'/1/25").pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/44h/0h/0h/1/25'))), xpriv2.derive_path("44'/0'/0'/1/25").priv) with self.assertRaises(BIP32PathTemplateViolation): ks.get_pubkey( xpub49.derive_path('50001').pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/49h/0h/0h/0/50001'))) with self.assertRaises(BIP32PathTemplateViolation): ks.get_pubkey( xpub49.derive_path('50000/3').pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/49h/0h/0h/0/50000/3'))) self.assertEqual( ks.get_pubkey( xpub49.derive_path('50000').pub.key_id, KeyDerivationInfo(xpriv2.fingerprint, BIP32Path('m/49h/0h/0h/0/50000'))), xpub49.derive_path('50000').pub)
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:
path_template = None require_path_templates = True if args.path_template is not None: if args.without_path_template_checks: print('--without-path-template-checks conflicts with ' '--path-template argument') sys.exit(-1) path_template = BIP32PathTemplate(args.path_template) elif args.without_path_template_checks: require_path_templates = False keys = [] for key_index, key_data in enumerate(args.key or []): k: Optional[Union[CCoinKey, CCoinExtKey]] = None try: k = CCoinKey(key_data) except (ValueError, Base58Error): pass try: k = CCoinExtKey(key_data) except (ValueError, Base58Error): pass if k is None: print(f'key at position {key_index} is not in recognized format') sys.exit(-1) keys.append(k) psbt = PartiallySignedTransaction.from_base64_or_binary(psbt_data) sign_result = psbt.sign(KeyStore.from_iterable(
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. 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
def sign_message(key, msg): secret = CCoinKey(key) message = BitcoinMessage(msg) return SignMessage(secret, message)
def sign_message(key: str, msg: str) -> bytes: secret = CCoinKey(key) message = BitcoinMessage(msg) return SignMessage(secret, message)
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:
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() ]