Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: waxwing on October 24, 2013, 09:38:56 PM



Title: Construction of multisig address
Post by: waxwing on October 24, 2013, 09:38:56 PM
Can anybody show me where in the bitcoin source the construction of multisig addresses occurs? I found the createmultisig method in script.cpp which creates a CScript object, but I can't see exactly where that gets converted to a base58 address. I'm trying to make sure I understand exactly how it's done. I know it's written here (https://en.bitcoin.it/wiki/Base58Check_encoding), but I'm not getting the correct result here (https://bitcointalk.org/index.php?topic=271343.msg3403253#msg3403253), so I need somehow to audit each step. Thanks for any pointers.


Title: Re: Construction of multisig address
Post by: kjj on October 25, 2013, 02:56:18 PM
I'm not sure about the main client, but here is some ghetto PHP code that works.  I've used it to create a bunch of multisig p2sh addresses.

Code: (multisig.php)
function createmultisig($nReq,$keys,$sortkeys=TRUE){
 $debug=FALSE;

 // I always sort keys so that I end up with a canonical p2sh address for any given set of keys and parameters
 // if you are testing this against another implementation, disable the sorting, or put them in sorted order before calling the other code
 if($sortkeys)sort($keys,SORT_STRING);

 // P2SH multisig in bitcoin requires between 2 and 16 (inclusive) keys
 // this appears mostly to be because of the single-byte PUSH_x opcodes, 0x52 to 0x60
 if($nReq<2 OR $nReq>16 OR $nReq>count($keys))return FALSE;

 // the structure of P2SH multisig is very simple.  This short block assembles the redeemscript
 $rs=chr(0x50+$nReq);
 while(list($key,$val)=each($keys)){
  $bpk=hex2bin($val);
  $rs.=chr(strlen($bpk)).$bpk;
 }
 $rs.=chr(0x50+count($keys));
 $rs.=chr(0xae);

 // this block then turns the redeem script into an address.
 // the debug lines allow easy verification of each step to compare with published examples

 if($debug)echo "In: ".$rs."\n";
 $h=hash("sha256",$rs,TRUE);
 if($debug)echo "H: ".bin2hex($h)."\n";
 $h2=hash("ripemd160",$h,TRUE);
 if($debug)echo "H2: ".bin2hex($h2)."\n";
 $h3="\x05".$h2;
 if($debug)echo "H3: ".bin2hex($h3)."\n";
 $h4=hash("sha256",$h3,TRUE);
 if($debug)echo "H4: ".bin2hex($h4)."\n";
 $h5=hash("sha256",$h4,TRUE);
 if($debug)echo "H5: ".bin2hex($h5)."\n";
 $chk=substr($h5,0,4);
 if($debug)echo "Chk: ".bin2hex($chk)."\n";
 $addr_bin=$h3.$chk;
 if($debug)echo "addr: ".bin2hex($addr_bin)."\n";
 $addr=encodeBase58($addr_bin);
 if($debug)echo $addr."\n";

 return array("redeemScript"=>bin2hex($rs),"address"=>$addr);
}


Title: Re: Construction of multisig address
Post by: waxwing on October 25, 2013, 05:39:58 PM
Thanks for the suggestion. The problem I was having turned out to be down to blockchain.info not accepting raw multisig txs. I've found another way (using electrum) for now.