etotheipi (OP)
Legendary
Offline
Activity: 1428
Merit: 1093
Core Armory Developer
|
|
August 11, 2013, 01:05:42 PM |
|
That's an amateurish problem that only happens with custom implementations of ECDSA. You have to use a random number when calculating the signature, and every basic implementation of ECDSA guarantees this (at least to the extent of the randomness it can pull from your system). The problem there was people hand-rolling their own and not realizing that reusing "random" numbers when signing different messages with the same key reveals the private key. This was the same reason that Sony's PS3 signing key was compromised: https://groups.google.com/forum/#!topic/sci.crypt/3isJl28Slrw Each key (for each different type of loader) seems to have an associated random number ‘m’ — the numbers follow no pattern, but they are consistent between different signatures on different versions of the same loader — almost as if they treated ‘m’ as one of the parameters of the key.
If I understand correctly this means Sony decided they were smart enough to reimplement their own version of ECDSA from scratch. Famous last word. Armory is unaffected. And for reference, you don't even need good random numbers for it. You just need anything that changes between signatures and looks random.
|
|
|
|
winnetou
|
|
August 11, 2013, 01:07:45 PM |
|
That's an amateurish problem that only happens with custom implementations of ECDSA. You have to use a random number when calculating the signature, and every basic implementation of ECDSA guarantees this (at least to the extent of the randomness it can pull from your system). The problem there was people hand-rolling their own and not realizing that reusing "random" numbers when signing different messages with the same key reveals the private key. This was the same reason that Sony's PS3 signing key was compromised: https://groups.google.com/forum/#!topic/sci.crypt/3isJl28Slrw Each key (for each different type of loader) seems to have an associated random number ‘m’ — the numbers follow no pattern, but they are consistent between different signatures on different versions of the same loader — almost as if they treated ‘m’ as one of the parameters of the key.
If I understand correctly this means Sony decided they were smart enough to reimplement their own version of ECDSA from scratch. Famous last word. Armory is unaffected. And for reference, you don't even need good random numbers for it. You just need anything that changes between signatures and looks random. Thank you very much for that information! I really trust your wallet and I love it that you are really caring about a good implementation and testing etc of your wallet!
|
|
|
|
chrcoe01
|
|
August 12, 2013, 02:32:45 PM |
|
I have a question regarding scripting with armory.
say for instance I was wanting to set up a custom script utilizing bitcoin's sendmany RPC command. Normally, if I were not using the armory cold storage (or armory at all), this would be a fairly simple matter being able to just call the command.
Since I want to do this via armory's cold storage, I would need to create the offline transaction but I am having a hard time trying to find info regarding how to do this in a script as opposed to using the GUI and manually choosing every single address I want to send to.
I am envisioning a script where I can pull in a list of addresses and payment amounts, check that there are no duplicates, if there are, combine the payout amounts and send the addresses and their payments into sendmany, create the offline transaction and have it save the output to a file that I can then go to my offline wallet to sign (this I would do manually as it doesn't take much time).
Then I would just continue normally without the script from there (go back to online and broadcast it). This would save me a ton of time manually entering addresses into armory.
I used to do this with the bitcoin client, but I moved to armory a long time ago and it's been bugging me recently.
Any insights? Is it possible that I'm just missing an important piece to the puzzle? Since Armory uses the bitcoin client on the backend, I wonder if the scripting would be the same, but the bitcoin client wouldn't have the offline data (ie private keys) this is what is throwing me currently.
|
"You may delay, but time will not, and lost time is never found again." -Benjamin Franklin
|
|
|
etotheipi (OP)
Legendary
Offline
Activity: 1428
Merit: 1093
Core Armory Developer
|
|
August 12, 2013, 02:41:40 PM Last edit: August 12, 2013, 03:22:07 PM by etotheipi |
|
Check BitcoinArmory/extras/createTxFromAddrList.py. Also sample_armory_code.py in that same directory has a lot of useful stuff. Admittedly, some of the examples, including createTxFromAddrList.py, uses an old version of the blockchain utiltiies -- for instance, BDM_LoadBlockchainFile() no longer works/exists. If you see this: BDM_LoadBlockchainFile() walletObj.setBlockchainSyncFlag(BLOCKCHAIN_READONLY) walletObj.syncWithBlockchain()
Replace it with this: TheBDM.setBlocking(True) TheBDM.setOnlineMode(True) TheBDM.scanBlockchainForTx(wlt.cppWallet)
Other than that, I think everything is the same, so you have an almost-full solution there! Also check extras/cli_sign_txdp.py which can be used on the offline computer to load your wallet, load an unsigned transaction, unlock your wallet, get your confirmation, and then sign it for you. Try it out! I made both of these to help scripters like you
|
|
|
|
w00dy
Member
Offline
Activity: 96
Merit: 10
|
|
August 12, 2013, 03:18:18 PM |
|
well... for me it still crash on every try.
- i have 8 GB RAM - i have 64 Bit win7
it worked fine up untill 0.85something (i think).
This is the case on my Laptop AND on my PC (both 64 + 8GB) and i pretty much gave up for now...
|
|
|
|
etotheipi (OP)
Legendary
Offline
Activity: 1428
Merit: 1093
Core Armory Developer
|
|
August 12, 2013, 03:21:52 PM |
|
well... for me it still crash on every try.
- i have 8 GB RAM - i have 64 Bit win7
it worked fine up untill 0.85something (i think).
This is the case on my Laptop AND on my PC (both 64 + 8GB) and i pretty much gave up for now...
Have you completely uninstalled and reinstalled? Sometimes the installer doesn't replace the old files properly when you are upgrading. I've tried multiple things to fix that, but it doesn't work.
|
|
|
|
chrcoe01
|
|
August 12, 2013, 03:22:11 PM |
|
Check BitcoinArmory/extras/createTxFromAddrList.py. Also sample_armory_code.py in that same directory has a lot of useful stuff. Admittedly, some of the examples, including createTxFromAddrList.py, uses an old version of the blockchain utiltiies -- for instance, BDM_LoadBlockchainFile() no longer works/exists. If you see this: BDM_LoadBlockchainFile() walletObj.setBlockchainSyncFlag(BLOCKCHAIN_READONLY) walletObj.syncWithBlockchain()
TheBDM.setBlocking(True) TheBDM.setOnlineMode(True) TheBDM.scanBlockchainForTx(wlt.cppWallet)
Other than that, I think everything is the same, so you have an almost-full solution there! Also check extras/cli_sign_txdp.py which can be used on the offline computer to load your wallet, load an unsigned transaction, unlock your wallet, get your confirmation, and then sign it for you. Try it out! I made both of these to help scripters like you that's fantastic, thanks for the super quick response. I wasn't expecting to hear back until tonight! I'll work on it tonight. did I mention I love python? thanks again
|
"You may delay, but time will not, and lost time is never found again." -Benjamin Franklin
|
|
|
chrcoe01
|
|
August 12, 2013, 04:02:01 PM |
|
so could I actually load the chain and scan for up to date transaction using this script without actually loading the GUI to scan the chain? basically add a step to the beginning process of script to load/scan the chain (assuming that bitcoin-qt is currently loaded and up to date), then continue on with my previous logic? Also, were you meaning that: BDM_LoadBlockchainFile() walletObj.setBlockchainSyncFlag(BLOCKCHAIN_READONLY) walletObj.syncWithBlockchain() is replaced with: TheBDM.setBlocking(True) TheBDM.setOnlineMode(True) TheBDM.scanBlockchainForTx(wlt.cppWallet) to put armory into online mode and scan the chain?
|
"You may delay, but time will not, and lost time is never found again." -Benjamin Franklin
|
|
|
etotheipi (OP)
Legendary
Offline
Activity: 1428
Merit: 1093
Core Armory Developer
|
|
August 12, 2013, 04:18:20 PM |
|
so could I actually load the chain and scan for up to date transaction using this script without actually loading the GUI to scan the chain? basically add a step to the beginning process of script to load/scan the chain (assuming that bitcoin-qt is currently loaded and up to date), then continue on with my previous logic? Also, were you meaning that: BDM_LoadBlockchainFile() walletObj.setBlockchainSyncFlag(BLOCKCHAIN_READONLY) walletObj.syncWithBlockchain() is replaced with: TheBDM.setBlocking(True) TheBDM.setOnlineMode(True) TheBDM.scanBlockchainForTx(wlt.cppWallet) to put armory into online mode and scan the chain? That's correct. Everything the GUI does could be done from python scripts. In fact, you could think of the GUI as one big python script that simply uses the utilities provided by armoryengine.py (and the massive set of underlying C++ utilities). I've tried to keep the bulk of the functionality in armoryengine.py so that you don't have to import any Qt libraries in order to script it headlessly like this. There's still lots of example code in ArmoryQt.py and qtdialogs.py that could be useful, but everything that Armory GUI can do, can be done through scripts without any GUI interaction. If you run the cli_sign_txdp.py script, you'll see that it does the same thing as GUI, but through a text/terminal interface. To continue discussion on this, it might be worth starting a new thread, to help aggregate this kind of information into a single place for others wishing to do scripting.
|
|
|
|
w00dy
Member
Offline
Activity: 96
Merit: 10
|
|
August 12, 2013, 04:46:26 PM |
|
well... for me it still crash on every try.
- i have 8 GB RAM - i have 64 Bit win7
it worked fine up untill 0.85something (i think).
This is the case on my Laptop AND on my PC (both 64 + 8GB) and i pretty much gave up for now...
Have you completely uninstalled and reinstalled? Sometimes the installer doesn't replace the old files properly when you are upgrading. I've tried multiple things to fix that, but it doesn't work. as far as i know - yes.
|
|
|
|
etotheipi (OP)
Legendary
Offline
Activity: 1428
Merit: 1093
Core Armory Developer
|
|
August 12, 2013, 04:59:45 PM |
|
When exactly does it crash? Does it not open at all? Or does it start to open then crash immediately? Do you use a native language other than English? The most recent version had an issue with non-ASCII/non-English characters. If so, you can go to the downloads page and try 0.87.2. Many users have reported that working even when 0.88.1 doesn't. (Googlecode downloads page: https://code.google.com/p/bitcoinarmory/downloads/list) As soon as I finish this RAM upgrade, I will have time to address these things. Getting closer!
|
|
|
|
cp1
|
|
August 12, 2013, 05:15:29 PM |
|
Here's my code for my watching only script to load the blockchain and read a balance for some addresses. Hope this helps. import sys sys.path.append('..') sys.path.append('.')
from armoryengine import * from time import sleep start = RightNow()
TheBDM.setBlocking(True) TheBDM.setOnlineMode(True) print 'Loading blockchain took %0.1f sec' % (RightNow() - start) start = RightNow() topBlock = TheBDM.getTopBlockHeight() print '\n\nCurrent Top Block is:', topBlock TheBDM.getTopBlockHeader().pprint()
cppWallet = Cpp.BtcWallet() cppWallet.addAddress_1_( addrStr_to_hash160("1ArmoryXcfq7TnCSuZa9fQjRYwJ4bkRKfv") )
print cppWallet.getNumAddr(),' addresses in this wallet' print '\n\nRegistering the wallet with the BlockDataManager & loading...' TheBDM.registerWallet(cppWallet) TheBDM.scanBlockchainForTx(cppWallet) print '\n\nTransaction history of this wallet:' ledger = cppWallet.getTxLedger() for le in ledger: le.pprintOneLine() print '\n\n************************************\nBalance of this wallet:', coin2str(cppWallet.getSpendableBalance()) print 'Unspent outputs:' unspentTxOuts = cppWallet.getSpendableTxOutList(topBlock) for utxo in unspentTxOuts: utxoAddr = hash160_to_addrStr(utxo.getRecipientAddr()) print utxoAddr," ",float(utxo.getValue())/100000000.0, " ",utxo.getNumConfirm()
while True: if TheBDM.getBDMState()=='BlockchainReady': prevTopBlock = TheBDM.getTopBlockHeight() newBlks = TheBDM.readBlkFileUpdate() if newBlks>0: print newBlks," new blocks found" latestBlockNum = TheBDM.getTopBlockHeight() topTimestamp = TheBDM.getTopBlockHeader().getTimestamp() TheBDM.scanBlockchainForTx(cppWallet) print '\n\nTransaction history of this wallet:' ledger = cppWallet.getTxLedger() for le in ledger: le.pprintOneLine() print '\n\n************************************\nBalance of this wallet:', coin2str(cppWallet.getSpendableBalance()) print 'Unspent outputs:' unspentTxOuts = cppWallet.getSpendableTxOutList(topBlock) for utxo in unspentTxOuts: utxoAddr = hash160_to_addrStr(utxo.getRecipientAddr()) print utxoAddr," ",float(utxo.getValue())/100000000.0, " ",utxo.getNumConfirm() time.sleep(10)
|
|
|
|
w00dy
Member
Offline
Activity: 96
Merit: 10
|
|
August 12, 2013, 05:53:51 PM |
|
When exactly does it crash? Does it not open at all? Or does it start to open then crash immediately? Do you use a native language other than English? The most recent version had an issue with non-ASCII/non-English characters. If so, you can go to the downloads page and try 0.87.2. Many users have reported that working even when 0.88.1 doesn't. (Googlecode downloads page: https://code.google.com/p/bitcoinarmory/downloads/list) As soon as I finish this RAM upgrade, I will have time to address these things. Getting closer! Sorry for the lack of info from my side! i'm using a German W7 Ultimate so i could switch to english (will try later) i can start it and it loads the blockchain (armory-bitcoind / manual-bitcoind makes no difference at all crash wise) up to a point where it need ~2.5G of real working set RAM. Then it just crash. Name der fehlerhaften Anwendung: Armory.exe, Version: 0.0.0.0, Zeitstempel: 0x4918017b Name des fehlerhaften Moduls: _CppBlockUtils.pyd, Version: 0.0.0.0, Zeitstempel: 0x5171c370 Ausnahmecode: 0xc0000005 Fehleroffset: 0x0000000000005050 ID des fehlerhaften Prozesses: 0x2030 Startzeit der fehlerhaften Anwendung: 0x01ce976d75b4f412 Pfad der fehlerhaften Anwendung: C:\Program Files (x86)\Armory\Armory Bitcoin Client\Armory.exe Pfad des fehlerhaften Moduls: C:\Program Files (x86)\Armory\Armory Bitcoin Client\_CppBlockUtils.pyd Berichtskennung: 666872b4-0361-11e3-872c-f3fba52936f1 Please note i closed EVERYTHING i could to bring down real RAM usage of my system to around 1.4G of 8. This laptop is rock solid for everything else. It's running hours every day, with RAM hungry VM's, games and what not. Will try older versions again but like i said... it's crashing for months.
|
|
|
|
runeks
Legendary
Offline
Activity: 980
Merit: 1008
|
|
August 12, 2013, 07:02:23 PM |
|
etotheipi, are you watching the development in bitcoind regarding the importaddress RPC method? Commenting on that issue, it got me thinking that this is perfect for Armory (and all other wallets that interface with bitcoind/qt). Just let Armory handle the wallet/private keys, and then add the addresses to bitcoind using this RPC method, and you can query it for transactions involving the addresses in question using listtransactions. This saves the double work of first letting Bitcoin sort everything out while it's downloading the block chain, and then having Armory scan the blockchain for transactions again. Armory would be able to start instantly, and update the balances as bitcoind updates the blockchain and the list of transactions referencing the addresses added via importaddress. Would this work do you think?
|
|
|
|
chrcoe01
|
|
August 12, 2013, 08:32:08 PM |
|
Here's my code for my watching only script to load the blockchain and read a balance for some addresses. Hope this helps. import sys sys.path.append('..') sys.path.append('.')
from armoryengine import * from time import sleep start = RightNow()
TheBDM.setBlocking(True) TheBDM.setOnlineMode(True) print 'Loading blockchain took %0.1f sec' % (RightNow() - start) start = RightNow() topBlock = TheBDM.getTopBlockHeight() print '\n\nCurrent Top Block is:', topBlock TheBDM.getTopBlockHeader().pprint()
cppWallet = Cpp.BtcWallet() cppWallet.addAddress_1_( addrStr_to_hash160("1ArmoryXcfq7TnCSuZa9fQjRYwJ4bkRKfv") )
print cppWallet.getNumAddr(),' addresses in this wallet' print '\n\nRegistering the wallet with the BlockDataManager & loading...' TheBDM.registerWallet(cppWallet) TheBDM.scanBlockchainForTx(cppWallet) print '\n\nTransaction history of this wallet:' ledger = cppWallet.getTxLedger() for le in ledger: le.pprintOneLine() print '\n\n************************************\nBalance of this wallet:', coin2str(cppWallet.getSpendableBalance()) print 'Unspent outputs:' unspentTxOuts = cppWallet.getSpendableTxOutList(topBlock) for utxo in unspentTxOuts: utxoAddr = hash160_to_addrStr(utxo.getRecipientAddr()) print utxoAddr," ",float(utxo.getValue())/100000000.0, " ",utxo.getNumConfirm()
while True: if TheBDM.getBDMState()=='BlockchainReady': prevTopBlock = TheBDM.getTopBlockHeight() newBlks = TheBDM.readBlkFileUpdate() if newBlks>0: print newBlks," new blocks found" latestBlockNum = TheBDM.getTopBlockHeight() topTimestamp = TheBDM.getTopBlockHeader().getTimestamp() TheBDM.scanBlockchainForTx(cppWallet) print '\n\nTransaction history of this wallet:' ledger = cppWallet.getTxLedger() for le in ledger: le.pprintOneLine() print '\n\n************************************\nBalance of this wallet:', coin2str(cppWallet.getSpendableBalance()) print 'Unspent outputs:' unspentTxOuts = cppWallet.getSpendableTxOutList(topBlock) for utxo in unspentTxOuts: utxoAddr = hash160_to_addrStr(utxo.getRecipientAddr()) print utxoAddr," ",float(utxo.getValue())/100000000.0, " ",utxo.getNumConfirm() time.sleep(10)
this is helpful for sure! etotheipi - I spent the last hour or two going through the example scripts, I am sure I will be able to get it going how I want, if I need to discuss this more, I may split it out as you suggest.
|
"You may delay, but time will not, and lost time is never found again." -Benjamin Franklin
|
|
|
cp1
|
|
August 12, 2013, 09:26:29 PM |
|
I guess I shouldn't say it's my code -- it's all stolen and cobbled together from the example scripts etotheipi gave.
|
|
|
|
Roy Badami
|
|
August 12, 2013, 10:02:56 PM |
|
That's an amateurish problem that only happens with custom implementations of ECDSA. You have to use a random number when calculating the signature, and every basic implementation of ECDSA guarantees this (at least to the extent of the randomness it can pull from your system). The problem there was people hand-rolling their own and not realizing that reusing "random" numbers when signing different messages with the same key reveals the private key.
What do you think of this? Is it safe? (Or is it too new to say?) https://tools.ietf.org/html/rfc6979
|
|
|
|
chrcoe01
|
|
August 13, 2013, 10:48:03 PM |
|
I was working on my script and everything is going well following the samples as you suggested was helpful. What I'm stuck on now is converting the createTxFromAddrList.py to make it so at the end instead of signing and checking etc, it would export the unsigned tx file that I can copy to my offline wallet. Basically everything works perfectly how I want it to build the transaction, but I am having a hell of a time finding how to export the details to a tx file. So up to and including: print 'Creating Unsigned Transaction...' txdp = createTxFromAddrList(wlt, addrList, recipList, 50000, sendChangeTo) txdp.pprint() works well. and it prints out a lot of details showing where the unspent outputs are coming from and where they are going etc. I am trying to do this while having a hell of a time with the documentation so finding the right functions becomes a bit more challenging. I also have the other side setup (using cli_sign_txdp.py as an example) to fit exactly how I need it to, just having trouble with the saving of the unsigned tx file. Anyone have any suggestions?
|
"You may delay, but time will not, and lost time is never found again." -Benjamin Franklin
|
|
|
etotheipi (OP)
Legendary
Offline
Activity: 1428
Merit: 1093
Core Armory Developer
|
|
August 13, 2013, 10:50:00 PM |
|
I was working on my script and everything is going well following the samples as you suggested was helpful. What I'm stuck on now is converting the createTxFromAddrList.py to make it so at the end instead of signing and checking etc, it would export the unsigned tx file that I can copy to my offline wallet. Basically everything works perfectly how I want it to build the transaction, but I am having a hell of a time finding how to export the details to a tx file. So up to and including: print 'Creating Unsigned Transaction...' txdp = createTxFromAddrList(wlt, addrList, recipList, 50000, sendChangeTo) txdp.pprint() works well. and it prints out a lot of details showing where the unspent outputs are coming from and where they are going etc. I am trying to do this while having a hell of a time with the documentation so finding the right functions becomes a bit more challenging. I also have the other side setup (using cli_sign_txdp.py as an example) to fit exactly how I need it to, just having trouble with the saving of the unsigned tx file. Anyone have any suggestions? Open a *.unsigned.tx file for writing and use the txdp.serializeAscii() method to dump it in the BIP 10 format which will be recognized by Armory GUI or cli_sign_txdp.py script. Also note that since the Armory GUI does most of these things, you can probably find examples of what you're looking for, by simply searching the Armory codebase. I haven't done it, but I'm sure if you search for "txdp" in the ArmoryQt.py and qtdialogs.py, there will only be a few hits, and one of them will be serializeAscii() and another one unserializeAscii(). I use ASCII/text for the encoding so that the data could theoretically be copied into emails, like ASCII-armored PGP data.
|
|
|
|
chrcoe01
|
|
August 13, 2013, 11:32:47 PM Last edit: August 14, 2013, 12:41:03 PM by chrcoe01 |
|
awesome, I thought that serializeAscii() function looked promising I'm working on it currently, and I also started browsing through qtdialogs.py to see what the GUI is actually doing on the backend to save the transaction files. So the key once I get the actual transaction data is to dump it into a file called *.unsigned.tx so the offline wallet will recognize it. I was wondering about that as well, thanks! And here I thought the hardest part would be pulling the data in from my DB.. then I remembered about python-mysqldb wrappers Edit: Thanks a ton for the input, I have almost everything done now, just doing cleanup of my code and adding DB update stuff but I have all the tx file I/O setup. It was really simple once you told me about the serializeAscii() function.
|
"You may delay, but time will not, and lost time is never found again." -Benjamin Franklin
|
|
|
|