Author

Topic: Raw Tx Tool - Use for coin control, and never accidentally pay a huge fee again! (Read 4541 times)

legendary
Activity: 1260
Merit: 1000
Drunk Posts
Someone should make this for Mac OSX Wink

Install Mono, it'll probably run fine as is.

Yes, if anyone is trying to run this on Mono, please send me any errors/missing dependencies, and I'll try to work around. None of my linux boxes have GUIs.

I've also updated the underlying Bitcoin Tool library to support signing p2sh and multisig tx, so it should work here, but as of now its completely untested.
sr. member
Activity: 369
Merit: 250
Someone should make this for Mac OSX Wink

Install Mono, it'll probably run fine as is.
legendary
Activity: 1008
Merit: 1000
New version posted, fixes a crash. Been using this to move several hundred bitcoins today.

Edit: added ability to read pasted raw tx

http://goo.gl/K64AQ4

https://github.com/mb300sd/RawTxTool/raw/master/bin/RawTxTool.exe

Thanks again for the ability to read raw tx's... I think that is REALLY AWESOME. Is the Blockchain.info guy listening? THIS WOULD BE REALLY GREAT IF THE PUSHTX PAGE ON BLOCKCHAIN.IFO PARSED RAW TXs SO YOU COULD SEE WHAT YOU ARE DOING BEFORE YOU BROADCAST!

I AM TYPING ALL CAPS BECAUSE I LOVE ALL OF YOU AND AM VERY EXCITED!  Grin
legendary
Activity: 1260
Merit: 1000
Drunk Posts
New version posted, fixes a crash. Been using this to move several hundred bitcoins today.

Edit: added ability to read pasted raw tx

http://goo.gl/K64AQ4

https://github.com/mb300sd/RawTxTool/raw/master/bin/RawTxTool.exe
legendary
Activity: 2053
Merit: 1356
aka tonikt

See BIP 10 for a transaction distribution format: https://en.bitcoin.it/wiki/BIP_0010

I'm not sure it's my favorite format, but it's the one concrete proposal right now.
Thanks.

To be honest, I prefer moving txs to/from my cold storage in a raw format.
Then I can easily check if a tx has not been tempered with, doing e.g.:
Code:
cat transaction.bin | openssl sha256 -binary | openssl sha256

Besides, before spending them my wallet app needs the original raw data anyway, to make sure that it has the expected ID.
So IMO, it is more convenient for a wallet app to have a tx (carrying an unspent output) as a raw data already.

And if I need to see whats inside a raw tx, I have a tool to display it in a human readable format.
I always use it on a signed tx, before moving it out from my cold storage. Just in case if my wallet would screw something up.

Code:
/*
gcc bctrans.c -o bctrans.exe -lcrypto -I /local/ssl/include -L /local/ssl/lib
*/

#include
#include
#include
#include
#include
#include


static unsigned char addr_version = 0x00;
static FILE *f = NULL;

BIGNUM *bn58, dv, mo;
BN_CTX *ctx;


#define SHA256(p,l,o) { \
SHA256_CTX shactx; \
SHA256_Init(&shactx); \
SHA256_Update(&shactx, (p), (l)); \
SHA256_Final((o), &shactx); }


void readfile(unsigned char *p, int len) {
if (!f) {
int c, i;
char s[3];
while (len>0) {
for (i=0;i<2;) {
c = getchar();
if (c==EOF) {
fprintf(stderr, "File too short\n");
exit(1);
}
c = tolower(c);
if (c<='9' && c>='0' || c<='f' && c>='a')  s[i++] = (char)c;
}
s[2] = 0;
sscanf(s, "%x", &c);
*p = (unsigned char)c;
p++;
len--;
}
} else {
if (fread(p, 1, len, f)!=len) {
fprintf(stderr, "File too short\n");
fclose(f);
exit(1);
}
}
}

unsigned long long getle(unsigned char *p, int bytes) {
unsigned long long res=0;
while (bytes--) {
res|= ((unsigned long long)(p[bytes]))<<(8*bytes);
}
return res;
}

unsigned long long getvl() {
unsigned char b[8];
readfile(b, 1);
switch (*b) {
case 0xfd:
readfile(b, 2);
return getle(b, 2);
case 0xfe:
readfile(b, 4);
return getle(b, 4);
case 0xff:
readfile(b, 8);
return getle(b, 8);
}
return *b;
}


void prhash(unsigned char *p, unsigned int l) {
while (l--) printf("%02x", p[l]);
}


void hexdump(unsigned char *p, unsigned int l) {
while (l--) printf("%02x", *p++);
}


void printbtcaddr(unsigned char *p) {
static const char *chrs = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
unsigned char mod;
char out[64];
int i=0, j=0;
BIGNUM *bn = BN_bin2bn(p, 25, NULL);
while (!BN_is_zero(bn)) {
BN_div(&dv, &mo, bn, bn58, ctx);
if (BN_bn2bin(&mo, &mod)==0)  mod = 0;
out[i++] = chrs[mod];
BN_copy(bn, &dv);
}
BN_free(bn);
while ((*p)==0) {
putchar('1');
p++;
}
while (i--)  putchar(out[i]);
}


int main(int argc, char * argv[]) {
static unsigned char buf[0x10000];
unsigned long long i, sl, txcnt, v;
unsigned va, vb;
int x;
long fpos;
char *fname = NULL;

for (x=1; x if (strcmp(argv[x], "-t")==0) {
addr_version = 0x6f; // testnet
} else {
fname = argv[x];
}
}

if (!fname) {
printf("Enter transactions hexdump data:\n");
} else {
f = fopen(fname, "rb");
if (!f) {
fprintf(stderr, "File %s not found\n", fname);
return 1;
}
}

readfile(buf, 4);
printf("Version: %llu\n", getle(buf, 4));

txcnt = getvl();
printf("TX IN cnt: %llu\n", txcnt);
for (i=0; i readfile(buf, 36);
sl = getvl();

printf("%6d) : ", (int)i);
prhash(buf, 32);
printf(" Idx=%2lld  sl=%lld", getle(buf+32, 4), sl);
readfile(buf, sl);
readfile(buf, 4);

printf(" seq=%x\n", (unsigned)getle(buf, 4));
}

txcnt = getvl();
printf("TX OUT cnt: %llu\n", txcnt);

ctx = BN_CTX_new();
bn58 = BN_bin2bn("\x3a", 1, NULL);
BN_init(&dv);
BN_init(&mo);

for (i=0; i readfile(buf, 8);
sl = getvl();
v = getle(buf, 8);
va = (unsigned)(v/100000000LL);
vb = (unsigned)(v%100000000LL);
printf("%6d) : %7u.%08u BTC", (int)i, va, vb, sl);
readfile(buf, sl);
if (sl!=25 || memcmp(buf, "\x76\xa9\x14", 3) || buf[23]!=0x88 || buf[24]!=0xac) {
printf("  WARNING! Unexpected SIG_SCRIPT:\n"); hexdump(buf, sl);
} else {
unsigned char dat[25];
unsigned char sha[SHA256_DIGEST_LENGTH];
unsigned char sha2[SHA256_DIGEST_LENGTH];
dat[0] = addr_version; // version
memcpy(dat+1, buf+3, 20);
SHA256(dat, 21, sha);
SHA256(sha, SHA256_DIGEST_LENGTH, sha2);
//printf("  chsum:%02x%02x%02x%02x", sha2[0], sha2[1], sha2[2], sha2[3]);
memcpy(dat+21, sha2, 4);
printf("  to address "); printbtcaddr(dat);
}
putchar('\n');
}

BN_free(bn58);
BN_CTX_free(ctx);

readfile(buf, 4);
printf("Lock Time: %llu\n", getle(buf, 4));

if (f) {
fpos = ftell(f);
fseek(f, 0, SEEK_END);
if (fpos!=ftell(f)) {
printf("WARNING!!! File too long. Only %ld bytes expected (%ld too many)\n",
fpos, ftell(f)-fpos);
} else {
printf("File size checked OK - %ld bytes\n", fpos);
}
fclose(f);
}

return 0;
}
legendary
Activity: 1596
Merit: 1100

See BIP 10 for a transaction distribution format: https://en.bitcoin.it/wiki/BIP_0010

I'm not sure it's my favorite format, but it's the one concrete proposal right now.

legendary
Activity: 1260
Merit: 1000
Drunk Posts
The issue with reading raw tx, and the above file format, is that it doesn't contain complete original txout, which is required to get the address and to sign the tx. (bitcoind only requires txid and vout because it has all the tx already)

I could add a gui popup with the output of decoderawtransaction if thats of any use.
Edit: added ability to decode pasted raw transaction, but requires access to bitcoind or blockchain

The current output format is
32 bytes txid
4 bytes vout
x bytes txout (same format as serialized into transaction)
repeat

The code uses my BitcoinTool library (https://github.com/mb300sd/Bitcoin-Tool) which has functions to directly read and write the binary formats used by bitcoind
legendary
Activity: 1008
Merit: 1000
Quick question... can this be used to "read" raw transactions? That is something I would really appreciate having!
legendary
Activity: 2053
Merit: 1356
aka tonikt
BTW guys, maybe we should think of some kind of standard for such a "wallet balance" file.

Because I also have a wallet app which does quite the same things and it would be cool if it could import the data from other blockchain sources, rather than only the one I developed myself. It would be nice if it could also take a file that e.g. "Raw Tx Tool" fetched from blockchain.info. It's very useful, since then you don't need any bitcoin node, but just your wallet and blockchain.info webpage and you can still receive and send money using a cold wallet of your choice.


What I use is a zip file that contains unspent.txt, where each line has a format of:
Code:
- # comment (amount, b58 address, etc - not mandatory)

Besides the text file, inside the zip, there is a number of .tx files, that carry a binary content of the transactions mentioned in the unspent.txt
legendary
Activity: 1260
Merit: 1000
Drunk Posts
Great stuff, man.

Think about adding an option to export the fetched inputs to a file - and then to get them from the file at another (offline) PC.

By this you will essentially turn your app into a nice cold wallet solution, that can work with bitcoind gateway, or even without it.

Done.

Binaries: https://mega.co.nz/#!5RZ1EboJ!LTvWpR3xXDY1vZYCtJzm5kWyTHt8TB-CQgvL1OaqTFU
legendary
Activity: 1596
Merit: 1100
Glad to see a GUI version of my txtool crop up Smiley   https://github.com/jgarzik/txtool/
legendary
Activity: 2053
Merit: 1356
aka tonikt
Great stuff, man.

Think about adding an option to export the fetched inputs to a file - and then to get them from the file at another (offline) PC.

By this you will essentially turn your app into a nice cold wallet solution, that can work with bitcoind gateway, or even without it.
legendary
Activity: 1260
Merit: 1000
Drunk Posts
Avoid horror stories like this one, https://bitcointalksearch.org/topic/1cfsaiyavfk12dnzpzalcrsp9jjwdk26fx-stop-making-transactions-296217

Use this tool for creating your raw transactions.
Lets you graphically build the transaction, selecting inputs from multiple sources at the same time.
Calculates total inputs, outputs and tx fee to prevent costly mistakes.
Sign transactions with keys from multiple sources.
Broadcast tx with a click of a button.



Source: https://github.com/mb300sd/RawTxTool
Binary: https://github.com/mb300sd/RawTxTool/raw/master/bin/RawTxTool.exe
Disassembler if you don't trust my binaries and can't compile: http://ilspy.net/

This is pre-alpha code. Please double check everything with decoderawtransaction in bitcoind if your dealing with significant amounts of coins. I am not responsible if this code causes loss of coins.
Jump to: