Bitcoin Forum

Bitcoin => Armory => Topic started by: chrisrico on October 05, 2014, 12:47:47 AM



Title: How to get a list of UXTOs?
Post by: chrisrico on October 05, 2014, 12:47:47 AM
Hi Armory dev team/community!

I'm trying to migrate my cold storage wallet from Armory to my Trezor. I have a bunch of outputs to different addresses, and what I'd like to do is create an UnsignedTransaction for each address, spending all of the funds (minus fees) to a Trezor address (assume I have a sufficient number of these available in a Python list). I've got a lot of these outputs, so I really don't want to do this through the GUI. I didn't see an easy way to do this using armoryd, so I am writing a Python script.

Here's my code so far:

Code:
import sys

sys.path.append('..')

from armoryengine.ALL import *

walletFile = "[REDACTED]"

wallet = PyBtcWallet().readWalletFile(walletFile)
TheBDM.registerWallet(wallet.cppWallet)

TheBDM.setOnlineMode(goOnline=True, wait=True)

for o in wallet.getTxOutList():
output = PyUnspentTxOut(o)
output.pprint()


TheBDM.execCleanShutdown(wait=True)

Every time I run this, I get a Segmentation fault with nothing in the logs. I'm on a Mac and am working from git master. Any ideas?

Here's what I do have in my logs:

Code:
-INFO  - 1412470223: (BlockUtils.cpp:4441) Finished blockchain scan in 6.04233 seconds
-INFO  - 1412470223: (BlockUtils.cpp:4460) Updating registered addresses
-INFO  - 1412470223: (BlockUtils.cpp:4468) Scanning Wallets
-INFO  - 1412470223: (BlockUtils.cpp:4479) Scanning Wallet #1 from height 0
-INFO  - 1412470223: (BlockUtils.cpp:4800) Saving wallet history to DB
Segmentation fault: 11


Title: Re: How to get a list of UXTOs?
Post by: etotheipi on October 05, 2014, 01:00:01 AM
First of all, there are some examples you can use in the extras directory in the project.  Also some stuff here:

https://bitcoinarmory.com/developers/python-scripting/

Those might be slightly out of date, but require minimal modification to make them work.  And for such a script, I recommend doing TheBDM.setBlocking(True), which is better for scripts ... it means that the BDM, while still in a separate thread, will behave like it's in the same thread, and every request will block until it's done.  The sample_armory_code.py in the extras directory shows you an example of both.

You can use wlt.getTxOutList('Spendable') to get a list C++ TxOut objects:

https://github.com/etotheipi/BitcoinArmory/blob/master/ui/TxFrames.py#L826

You can then run them right through Armory's coin-selection algorithm:

https://github.com/etotheipi/BitcoinArmory/blob/master/ui/TxFrames.py#L598

That should be enough to hold you over in the short-term :)


Title: Re: How to get a list of UXTOs?
Post by: chrisrico on October 05, 2014, 06:07:02 AM
Thanks for pointing me in the right direction. Here was my final script:

Code:
import sys

sys.path.append('..')

from armoryengine.ALL import *

receivingAddresses = [...]

walletFile = "..."

wallet = PyBtcWallet().readWalletFile(walletFile)
TheBDM.registerWallet(wallet.cppWallet)

TheBDM.setBlocking(doblock=True, newTimeout=60*60)
TheBDM.setOnlineMode()

for address in wallet.getAddrList():
uxto = wallet.getAddrTxOutList(address.getAddr160())
if len(uxto) == 0:
continue
addressBalance = sum([o.getValue() for o in uxto])
keyMap = {o.getRecipientScrAddr(): address.binPublicKey65.toBinStr() for o in uxto}
outputs = [[addrStr_to_script(receivingAddresses.pop()), addressBalance]]
tx = UnsignedTransaction().createFromTxOutSelection(uxto, outputs, keyMap)
fileName = "armory_{0}_{1}BTC.unsigned.tx".format(tx.asciiID, coin2str(addressBalance, 0, False, 0))
with open(fileName, 'w') as txFile:
txFile.write(tx.serializeAscii())

TheBDM.execCleanShutdown()

Basically, I wanted these unsigned transactions handy to more easily transfer funds to the Trezor as needed/became more comfortable with its security model. I wanted a 1-1 address correspondence between my Armory and Trezor addresses, with no mixing. Fees are negligible because they've been sitting around for so long.