Pages:
Author

Topic: MultiSig BUT with Bitcoin Addresses NOT Public Keys (Read 3086 times)

sr. member
Activity: 352
Merit: 252
https://www.realitykeys.com
Sweet. We should probably:
1) Write a test for the other branch as well
2) Try sending the tx to a 0.10 node before using blochain.info/pushtx on it to prove that the network will really take these things when it starts to upgrade.

1) Ok. I have to learn how to do a push request (I suck at GIT) and I'll make a suggestion to  your test.
2)  the blockchain.info method is a kind of a cheat ;-) But if it works ;-) but I'd LOVE to test that. I'm just happy it's working (and it worked. I got my 2 cents ;-) Who tests on the testnet any more ;-)


P.S. Your library will be talked about at tomorrow's Miami Bitcoin hackathon cause it's amazing. Thank you so much for helping me with this.

OK, I just went ahead and added those tests myself.

The redeem transaction went fine through a stock bitcoin 0.10, and enough of the network seems to have relayed it for it to show up on blockchain.info.
https://blockchain.info/tx/c6b283ed4f2742b3c5aca31380daa423e89620e95a53cddf3d81338dcca95b8c
Edit to add: And mined, also by Eligius. Discus Fish doesn't seem to be a thing any more...
sr. member
Activity: 352
Merit: 252
https://www.realitykeys.com
Who tests on the testnet any more ;-)

I'm liking this system where an address I control is hard-coded in the test code, and people test their code by sending real money to it...
newbie
Activity: 9
Merit: 0
Sweet. We should probably:
1) Write a test for the other branch as well
2) Try sending the tx to a 0.10 node before using blochain.info/pushtx on it to prove that the network will really take these things when it starts to upgrade.

1) Ok. I have to learn how to do a push request (I suck at GIT) and I'll make a suggestion to  your test.
2)  the blockchain.info method is a kind of a cheat ;-) But if it works ;-) but I'd LOVE to test that. I'm just happy it's working (and it worked. I got my 2 cents ;-) Who tests on the testnet any more ;-)


P.S. Your library will be talked about at tomorrow's Miami Bitcoin hackathon cause it's amazing. Thank you so much for helping me with this.
sr. member
Activity: 352
Merit: 252
https://www.realitykeys.com
Just updating the group.

We have created successfully a MultiSig Signature from JUST the Bitcoin Addresses (I think we're the first to do that, can't find anyone else online doing this.)
NO PUBKEY WAS USED (well the PubKey HASH was using, but not the original uncompressed full PubKey)

See transactions IN (the first from edmundedgar with the public Keys and the second from ME using the code below)

https://blockchain.info/address/3PcxJeW5f6Tp4mVAXe4ggGRvDREAPCMF4o


Thanks of course to everyone. And especially to edmundedgar for his amazing code examples INCLUDING his private keys (which makes live easier)

You need to do a:
1) download edmundedgar's Bitcoin Branching Transaction builder: https://github.com/edmundedgar/bitcoin-branching-transaction-builder
2) run "npm install bitcoinjs-lib" on that root directory
3) Make an app.js in the root of that project with the following code below (of course you have to have NODEjs installed)

Code:
var bitcoin = require('bitcoinjs-lib');
var BranchingTransactionBuilder = require('./src/branching_transaction_builder');
var ECKey = bitcoin.ECKey;
var Address = bitcoin.Address;
var scripts = bitcoin.scripts;

var BitcoinAddress1 = "1Fratqwo3Bu2FwMBzAex8WgDbmmGgJYLGH";
var BitcoinAddress2 = "112jFbM3Lp3qRSjezGFCv2rejT3UQ6rH5Z";

var addr1 =  Address.fromBase58Check(BitcoinAddress1);
var addr2 =  Address.fromBase58Check(BitcoinAddress2);

var branch1 = scripts.pubKeyHashOutput(addr1.hash);
var branch2 = scripts.pubKeyHashOutput(addr2.hash);


var branch_builder = new BranchingTransactionBuilder();
branch_builder.addSubScript(branch1);
branch_builder.addSubScript(branch2);
var branch_redeem_script = branch_builder.script();

var scriptPubKey = bitcoin.scripts.scriptHashOutput(branch_redeem_script.getHash())
var multisigAddress = bitcoin.Address.fromOutputScript(scriptPubKey).toString()
console.log("MultiSig Address: " + multisigAddress);
console.log("Redeem script: " + branch_redeem_script.buffer.toString('hex'));            


console.log("");
console.log("Ok. Now you FUND the account with something of MORE than 0.0001 bitcoins (that's the minimum)");
console.log("");

// Make Transaction
var Transaction = bitcoin.Transaction;
var TransactionBuilder = bitcoin.TransactionBuilder;

var BitcoinToSendTo = "1GzUEmh472VwWydkhY4vDQMqY3xFpZRcKs";
var addrToSendTo = Address.fromBase58Check(BitcoinToSendTo);
var branchToSendTo = scripts.pubKeyHashOutput(addrToSendTo.hash);

// Just repeating what's above to reiterate and segregate the code
BitcoinAddress2 = "112jFbM3Lp3qRSjezGFCv2rejT3UQ6rH5Z";
addr2 =  Address.fromBase58Check(BitcoinAddress2);
branch2 = scripts.pubKeyHashOutput(addr2.hash);

// Unspent amount: from https://blockchain.info/unspent?active=3PcxJeW5f6Tp4mVAXe4ggGRvDREAPCMF4o
            var test_output = {"unspent_outputs":[
                    {
                        "tx_hash":"3be8387e161bfc927cd4d06e4f1a800806ba509f74185709ee460967fe1d57c5",
                        "tx_hash_big_endian":"c5571dfe670946ee095718749f50ba0608801a4f6ed0d47c92fc1b167e38e83b",
                        "tx_index":74160687,
                        "tx_output_n": 0,
                        "script":"a914f08e151def9e83a2d96b44b5d87c719dcd374d8a87",
                        "value": 200000,
                        "value_hex": "030d40",
                        "confirmations":0
                    }
            ]};


var branch_redeem_script2 = branch_builder.script(branch_redeem_script.buffer.toString('hex'));
var spend_builder = new TransactionBuilder();
spend_builder.addInput(test_output['unspent_outputs'][0]['tx_hash_big_endian'], 0);
spend_builder.addOutput("1Dc8JwPsxxwHJ9zX1ERYo9q7NQA9SRLqbC", test_output['unspent_outputs'][0]['value'] - 10000);


var priv2 = ECKey.fromWIF('L3MRgBTuEtfvEpwb4CcGtDm4s79fDR8UK1AhVYcDdRL4pRpsy686');
var gp_builder = new BranchingTransactionBuilder(spend_builder);

// input 0 of the tx, second branch of 2 (index 1)
gp_builder.selectInputBranch(0, 1, 2);
gp_builder.signBranch(0, priv2, branch_redeem_script2, null, branchToSendTo);
var tx = gp_builder.build();

console.log(tx.toHex());


Sweet. We should probably:
1) Write a test for the other branch as well
2) Try sending the tx to a 0.10 node before using blochain.info/pushtx on it to prove that the network will really take these things when it starts to upgrade.
newbie
Activity: 9
Merit: 0
Just updating the group.

We have created successfully a MultiSig Signature from JUST the Bitcoin Addresses (I think we're the first to do that, can't find anyone else online doing this.)
NO PUBKEY WAS USED (well the PubKey HASH was using, but not the original uncompressed full PubKey)

See transactions IN (the first from edmundedgar with the public Keys and the second from ME using the code below)

https://blockchain.info/address/3PcxJeW5f6Tp4mVAXe4ggGRvDREAPCMF4o


Thanks of course to everyone. And especially to edmundedgar for his amazing code examples INCLUDING his private keys (which makes live easier)

You need to do a:
1) download edmundedgar's Bitcoin Branching Transaction builder: https://github.com/edmundedgar/bitcoin-branching-transaction-builder
2) run "npm install bitcoinjs-lib" on that root directory
3) Make an app.js in the root of that project with the following code below (of course you have to have NODEjs installed)

Code:
var bitcoin = require('bitcoinjs-lib');
var BranchingTransactionBuilder = require('./src/branching_transaction_builder');
var ECKey = bitcoin.ECKey;
var Address = bitcoin.Address;
var scripts = bitcoin.scripts;

var BitcoinAddress1 = "1Fratqwo3Bu2FwMBzAex8WgDbmmGgJYLGH";
var BitcoinAddress2 = "112jFbM3Lp3qRSjezGFCv2rejT3UQ6rH5Z";

var addr1 =  Address.fromBase58Check(BitcoinAddress1);
var addr2 =  Address.fromBase58Check(BitcoinAddress2);

var branch1 = scripts.pubKeyHashOutput(addr1.hash);
var branch2 = scripts.pubKeyHashOutput(addr2.hash);


var branch_builder = new BranchingTransactionBuilder();
branch_builder.addSubScript(branch1);
branch_builder.addSubScript(branch2);
var branch_redeem_script = branch_builder.script();

var scriptPubKey = bitcoin.scripts.scriptHashOutput(branch_redeem_script.getHash())
var multisigAddress = bitcoin.Address.fromOutputScript(scriptPubKey).toString()
console.log("MultiSig Address: " + multisigAddress);
console.log("Redeem script: " + branch_redeem_script.buffer.toString('hex'));           


console.log("");
console.log("Ok. Now you FUND the account with something of MORE than 0.0001 bitcoins (that's the minimum)");
console.log("");

// Make Transaction
var Transaction = bitcoin.Transaction;
var TransactionBuilder = bitcoin.TransactionBuilder;

var BitcoinToSendTo = "1GzUEmh472VwWydkhY4vDQMqY3xFpZRcKs";
var addrToSendTo = Address.fromBase58Check(BitcoinToSendTo);
var branchToSendTo = scripts.pubKeyHashOutput(addrToSendTo.hash);

// Just repeating what's above to reiterate and segregate the code
BitcoinAddress2 = "112jFbM3Lp3qRSjezGFCv2rejT3UQ6rH5Z";
addr2 =  Address.fromBase58Check(BitcoinAddress2);
branch2 = scripts.pubKeyHashOutput(addr2.hash);

// Unspent amount: from https://blockchain.info/unspent?active=3PcxJeW5f6Tp4mVAXe4ggGRvDREAPCMF4o
            var test_output = {"unspent_outputs":[
                    {
                        "tx_hash":"3be8387e161bfc927cd4d06e4f1a800806ba509f74185709ee460967fe1d57c5",
                        "tx_hash_big_endian":"c5571dfe670946ee095718749f50ba0608801a4f6ed0d47c92fc1b167e38e83b",
                        "tx_index":74160687,
                        "tx_output_n": 0,
                        "script":"a914f08e151def9e83a2d96b44b5d87c719dcd374d8a87",
                        "value": 200000,
                        "value_hex": "030d40",
                        "confirmations":0
                    }
            ]};


var branch_redeem_script2 = branch_builder.script(branch_redeem_script.buffer.toString('hex'));
var spend_builder = new TransactionBuilder();
spend_builder.addInput(test_output['unspent_outputs'][0]['tx_hash_big_endian'], 0);
spend_builder.addOutput("1Dc8JwPsxxwHJ9zX1ERYo9q7NQA9SRLqbC", test_output['unspent_outputs'][0]['value'] - 10000);


var priv2 = ECKey.fromWIF('L3MRgBTuEtfvEpwb4CcGtDm4s79fDR8UK1AhVYcDdRL4pRpsy686');
var gp_builder = new BranchingTransactionBuilder(spend_builder);

// input 0 of the tx, second branch of 2 (index 1)
gp_builder.selectInputBranch(0, 1, 2);
gp_builder.signBranch(0, priv2, branch_redeem_script2, null, branchToSendTo);
var tx = gp_builder.build();

console.log(tx.toHex());

newbie
Activity: 9
Merit: 0
Let's see that proof. Because if you can help me find the "publicKey" from my EXISTING blockchain.info

Here you go:
 (((( Image excluded )))

Proof accepted. I absolutely do for blockchain.info
And also like @amaclin said. Do I have it if I can look up a transaction from this public address in the past? (I mean that happened an hour ago) can I get the public key from the blockchain? After all If your about to FUND my new key. YOU have GOTTEN some money in the past.


Also. Does my code (see in the last post) trump this argument? (of which Danny you have won)
newbie
Activity: 9
Merit: 0
I just added a quick test for branching versions of pay-to-public-address-hash - hopefully this will make it clearer how it's supposed to work.

Alright. I think I have it. Here's a script that STARTS with your two BITCOIN ADDRESSES and ends with the same multiSig Key your test does.

BUT the redeem script looks too short. I'll have to try that transaction like you did yours.

Can you anything I'm doing wrong?

Code:
var bitcoin = require('bitcoinjs-lib');
var BranchingTransactionBuilder = require('./src/branching_transaction_builder');
var ECKey = bitcoin.ECKey;
var Address = bitcoin.Address;
var scripts = bitcoin.scripts;

var BitcoinAddress1 = "1Fratqwo3Bu2FwMBzAex8WgDbmmGgJYLGH";
var BitcoinAddress2 = "112jFbM3Lp3qRSjezGFCv2rejT3UQ6rH5Z";

var addr1 =  Address.fromBase58Check(BitcoinAddress1);
var addr2 =  Address.fromBase58Check(BitcoinAddress2);

var branch1 = scripts.pubKeyHashOutput(addr1.hash);
var branch2 = scripts.pubKeyHashOutput(addr2.hash);


var branch_builder = new BranchingTransactionBuilder();
branch_builder.addSubScript(branch1);
branch_builder.addSubScript(branch2);
var branch_redeem_script = branch_builder.script();

var scriptPubKey = bitcoin.scripts.scriptHashOutput(branch_redeem_script.getHash())
var multisigAddress = bitcoin.Address.fromOutputScript(scriptPubKey).toString()
console.log("MultiSig Address: " + multisigAddress);
console.log("Redeem script: " + branch_redeem_script.buffer.toString('hex')); 

RESULTS:
MultiSig Address: 3PcxJeW5f6Tp4mVAXe4ggGRvDREAPCMF4o
Redeem script: 6376a914a2f26faf639c9a7e6a3ae5076bf7bbbf6cf1732a88ac6776a9140053af91626c8e511b6 3f651161208b56ad0adac88ac68

legendary
Activity: 3528
Merit: 4945
Quote
- snip -
if you have a blockchain.info account. You DON'T have your public key.
In fact, you do.
Let's see that proof. Because if you can help me find the "publicKey" from my EXISTING blockchain.info
- snip -
then We've solve my initial problem.
- snip -

Here you go:

legendary
Activity: 1260
Merit: 1019
Quote
I want to make a 1of2 address and I have MY PubKey, but I don't have my mom's (or sisters, or friends) because they use a blockchain.info account and Android Wallet software.
If there are spending transactions from your mom's (sisters, friends, cats, dogs) addresses - you have their public keys
newbie
Activity: 9
Merit: 0
Quote
If you have the android client. if you have a blockchain.info account. You DON'T have your public key.

In fact, you do.

Let's see that proof. Because if you can help me find the "publicKey" from my EXISTING blockchain.info or android wallet accounts then We've solve my initial problem.

Real problem.

I want to make a 1of2 address and I have MY PubKey, but I don't have my mom's (or sisters, or friends) because they use a blockchain.info account and Android Wallet software.
legendary
Activity: 1260
Merit: 1168
This message was too old and has been purged
sr. member
Activity: 352
Merit: 252
https://www.realitykeys.com

@edmundedgar; using your code and  your "bitcoin-branching-transaction-builder" project (and Peter Todd's public Bitcoin Address so he could sign a TRANSACTION)

Code:
var bitcoin = require('bitcoinjs-lib');
var BranchingTransactionBuilder = require('./src/branching_transaction_builder');
var Script = bitcoin.Script;

var BitcoinAddress1 = "1KYestTGTEJzM5pR7AAQ7ckBE55ytLRaDk";
var BitcoinAddress2 = "1FCYd7j4CThTMzts78rh6iQJLBRGPW9fWv";
var rules = "OP_IF OP_DUP OP_HASH160 "+ BitcoinAddress1 + " OP_EQUALVERIFY OP_CHECKSIG. OP_ELSE OP_DUP OP_HASH160 " + BitcoinAddress2 + "  OP_EQUALVERIFY OP_CHECKSIG. OP_ENDIF";
var NewP2SHAddress = Script.fromASM(rules);

console.log(NewP2SHAddress.buffer.toString('hex'));


 I get a bitcoin address of: 6376a90088006776a900880068

Is this right? Where is the redeemScript


I just added a quick test for branching versions of pay-to-public-key-hash - hopefully this will make it clearer how it's supposed to work. Basically bitcoinlib-js takes care of making the bits inside the OP_IF branching, and my thing takes care of putting them together in a branching script, so you don't need to put in your own scripting from the ASM code or anything.
https://github.com/edmundedgar/bitcoin-branching-transaction-builder/blob/master/test/branching_transaction_builder.js#L81

Blockchain.info took my redeeming TX (the non-standard one) - let's see if it'll confirm in a reasonable time (or at all...)
https://blockchain.info/tx/7d8cf0dac56e90bfff76cee1a13464cc07f0ac36241b6703a894d28987630218
Edit to add: Yup, Eligius took it.

Some of the other suggestions people have made here will be variously more flexible (for more combinations of conditions) and more economical (in saving a few bytes) than mine, but you'll have to work out how to sign them since my code won't help you. YMMV, let us know how you get on...
legendary
Activity: 1792
Merit: 1122
This is a 2-of-2 multisig using "addresses"

Code:
OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG

1-of-2 multisig

Code:
OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_TOALTSTACK OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_FROMALTSTACK OP_ADD

2-of-3 multisig

Code:
OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_TOALTSTACK OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_TOALTSTACK OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_FROMALTSTACK OP_FROMALTSTACK OP_ADD OP_ADD OP_2 OP_EQUAL

However this is non-standard so not many miners will mine for you (P2SH may work?). Most importantly, none of the current bitcoin clients is able to create a signature for the script.
legendary
Activity: 1260
Merit: 1019
Quote
You can do "or" cases like this with branching OP_IFs (inside P2SH). Simplest case 1/2:
You also can do "and" cases inside P2SH
legendary
Activity: 1974
Merit: 1030
PubKeyHash = SHA-256(SHA-256(PubKey)
Address = Base58(version | PubKeyHash | checksum)

Nit: that should be RIPEMD-160(SHA-256(PubKey)).
donator
Activity: 1218
Merit: 1080
Gerald Davis
It is "OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG".
legendary
Activity: 1120
Merit: 1168
Code:
OP_IF
OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG.
OP_ELSE
OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG.
OP_ENDIF

1) Peter Todd. You say your version is better. But it seems to include the PubKeys. I need to include two (or at least one) Bitcoin Address (because I don't have the PubKey, they're not my addresses)
So will BIP19 help me here? and is it available now?

This about this a little harder: you can replace the CHECKSIG pattern in BIP19 with OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG.

The point of using BIP19 is it's more flexible; edmund's construction doesn't do n-of-m easily.
legendary
Activity: 1386
Merit: 1053
Please do not PM me loan requests!
Some addresses have known public keys on the block chain, but just looking for them wouldn't be very practical because not all addresses have known public keys. A newly generated address wouldn't have one on the chain; you'd need/want to have your customers give you their pubkeys directly, some way or another. Ideally, they would create a new address just for this contract.
donator
Activity: 1218
Merit: 1080
Gerald Davis
A quick tip both you and edmundedgar are conflating PubKeyHash with Address.   PubKey, PubKeyHas, and BitcoinAddress are distinct items.   An Address is a PubKeyHash (or ScriptHash) plus checksum and version data encoded in base58.    The Bitcoin network does not use Addresses.  Addresses are just for humans.  So in your code you would need to DECODE the Address to the PubKeyHash and at the end the result in a ScriptHash which then needs to be encoded as an address (if you are displaying it to a user).


PubKeyHash = RIPEMD-160(SHA-256(PubKey)
Address = Base58(version | PubKeyHash | checksum)

On edit: corrected hashing algorithm
newbie
Activity: 9
Merit: 0

@edmundedgar; using your code and  your "bitcoin-branching-transaction-builder" project (and Peter Todd's public Bitcoin Address so he could sign a TRANSACTION)

Code:
var bitcoin = require('bitcoinjs-lib');
var BranchingTransactionBuilder = require('./src/branching_transaction_builder');
var Script = bitcoin.Script;

var BitcoinAddress1 = "1KYestTGTEJzM5pR7AAQ7ckBE55ytLRaDk";
var BitcoinAddress2 = "1FCYd7j4CThTMzts78rh6iQJLBRGPW9fWv";
var rules = "OP_IF OP_DUP OP_HASH160 "+ BitcoinAddress1 + " OP_EQUALVERIFY OP_CHECKSIG. OP_ELSE OP_DUP OP_HASH160 " + BitcoinAddress2 + "  OP_EQUALVERIFY OP_CHECKSIG. OP_ENDIF";
var NewP2SHAddress = Script.fromASM(rules);

console.log(NewP2SHAddress.buffer.toString('hex'));


 I get a bitcoin address of: 6376a90088006776a900880068

Is this right? Where is the redeemScript
Pages:
Jump to: