ScriptPubKey | : OP_HASH160 <redeemScriptHash> OP_EQUAL |
ScriptSig | : OP_0 < ... > OP_PUSHDATA1 <redeemScript> |
Redeem Script | : < ... > OP_CHECKMULTISIG |
ScriptSig | : |
ScriptPubKey | : |
<?php use BitWasp\Bitcoin\Bitcoin; use BitWasp\Bitcoin\Network\NetworkFactory; use BitWasp\Buffertools\Buffer; use BitWasp\Bitcoin\Key\Factory\PublicKeyFactory; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Script\P2shScript; use BitWasp\Bitcoin\Script\Opcodes; include_once "../libraries/vendor/autoload.php"; $M_N_Range = range(1,15); include_once("html_iframe_header.php"); if ($_SERVER['REQUEST_METHOD'] == 'POST') { try { $networkClass = $_POST['network']; Bitcoin::setNetwork(NetworkFactory::$networkClass()); $network = Bitcoin::getNetwork(); $pubKeys = []; $publicKeyFactory = new PublicKeyFactory(); if (!in_array($_POST['reqsig'], $M_N_Range)) { throw new Exception("'Required Signature' value is not valid."); } else { foreach($_POST['pubkey'] as $pubkey_hex) { if (strlen($pubkey_hex) > 0 AND !ctype_xdigit($pubkey_hex)) { throw new Exception("Public key must be hex."); } if (strlen($pubkey_hex) > 0 AND ctype_xdigit($pubkey_hex)) { $validPubKeys[] = $publicKeyFactory->fromHex($pubkey_hex);; } } } if ($_POST['reqsig'] > count($validPubKeys)) { throw new Exception("Required signature value should not exceed number of public key."); } // make a n-of-m multisignature script $multisig = ScriptFactory::scriptPubKey()->multisig($_POST['reqsig'], $validPubKeys, $sort = false); // use the P2shScript 'decorator' to 'extend' script with extra functions relevant to a P2SH script $redeemScript = new P2shScript($multisig); $scriptPubKey = $redeemScript->getOutputScript(); $opcodes = $scriptPubKey->getOpcodes(); ?> <div class="table-responsive"> <h6 class="mt-3">P2SH.Multisig</h6> <table border=0 class='table'> <tr style='background-color:#f0f0f0'><td>Base58 address</td><td><?php echo $redeemScript->getAddress()->getAddress();?></td></tr> <tr><td>Redeem Script Hex </td><td><?php echo $redeemScript->getHex();?></td></tr> <tr><td>Redeem Script Asm</td> <td> <?php foreach( $redeemScript->getScriptParser()->decode() as $operation ) { if ($operation->isPush()) { echo htmlentities("<{$operation->getData()->getHex()}> "); } else { echo $opcodes->getOp($operation->getOp()) . " " ; } } ?> </td> </tr> <tr><td>Redeem Script Hash Hex</td><td><?php echo $redeemScript->getScriptHash()->getHex();?></td></tr> <tr style='background-color:#f0f0f0'><td>ScriptPubKey Hex </td><td><?php echo $scriptPubKey->getHex()?></td></tr> <tr style='background-color:#f0f0f0'><td>ScriptPubKey Asm</td> <td> <?php foreach( $scriptPubKey->getScriptParser()->decode() as $operation ) { if ($operation->isPush()) { echo htmlentities("<{$operation->getData()->getHex()}> "); } else { echo $opcodes->getOp($operation->getOp()) . " " ; } } ?> </td> </tr> </table> <?php if (@count($validPubKeys) <= 3) { ?> <h6 class="mt-3">P2MS</h6> <table border=0 class='table'> <tr><td>ScriptPubKey Hex </td><td><?php echo $redeemScript->getHex();?></td></tr> <tr><td>ScriptPubKey Asm</td> <td> <?php foreach( $redeemScript->getScriptParser()->decode() as $operation ) { if ($operation->isPush()) { echo htmlentities("<{$operation->getData()->getHex()}> "); } else { echo $opcodes->getOp($operation->getOp()) . " " ; } } ?> </td> </tr> </table> <?php } ?> </div> <?php } catch (Exception $e) { $errmsg .= "Problem found. " . $e->getMessage(); } } if ($errmsg) { ?> <div class="alert alert-danger"> <strong>Error!</strong> <?php echo $errmsg?> </div> <?php } ?> <form action='' method='post'> <div class="form-group"> <label for="network">Network:</label> <select id="network" name="network" class="form-control" > <?php $networks = get_class_methods(new NetworkFactory()); foreach($networks as $network) { echo "<option value='{$network}'".($network == $_POST['network'] ? " selected": "").">{$network}</option>"; } ?> </select> </div> <div class="form-group"> <label for="pubkey">Public Key Hex:</label> <div class="input-group mb-3"> <input class="form-control" type='text' name='pubkey[]' id='pubkey' value='<?php echo $_POST['pubkey'][0]?>'> <div class="input-group-append"> <input class="btn btn-success" type="button" value="+" onclick="$('#multisig-pubkey-holder').find('div').first().clone().appendTo('#multisig-pubkey-holder')"/> </div> </div> </div> <?php $displayPublickey = count($_POST['pubkey'])-1; $displayPublickey = max(1, $displayPublickey); ?> <div id="multisig-pubkey-holder" class="form-group"> <?php foreach(range(1, $displayPublickey) as $n) { ?> <div class="input-group mb-3"> <input class="form-control" type='text' name='pubkey[]' value='<?php echo $_POST['pubkey'][$n]?>'> <div class="input-group-append"> <input class="btn btn-success" type="button" value=" - " onclick=" var length = $(this).closest('#multisig-pubkey-holder').find('input[value=\' - \']').length; if (length > 1) { $(this).parent('div').parent('div').remove(); } else { alert('At least 2 public keys are required'); } "/> </div> </div> <?Php } ?> </div> <div class="form-group"> <label for="reqsig">Required Signature To Spend:</label> <select id="reqsig" name="reqsig" class="form-control" > <?php foreach($M_N_Range as $k) { echo "<option value='{$k}'".($k == $_POST['reqsig'] ? " selected": "").">{$k}</option>"; } ?> </select> </div> <input type='submit' class="btn btn-success btn-block"/> </form> <?php include_once("html_iframe_footer.php");
<?php use BitWasp\Bitcoin\Bitcoin; use BitWasp\Buffertools\Buffer; use BitWasp\Bitcoin\Network\NetworkFactory; use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory; use BitWasp\Bitcoin\Address\AddressCreator; use BitWasp\Bitcoin\Transaction\Factory\TxBuilder; use BitWasp\Bitcoin\Transaction\TransactionFactory; use BitWasp\Bitcoin\Transaction\TransactionOutput; use BitWasp\Bitcoin\Transaction\Factory\Signer; use BitWasp\Bitcoin\Script\ScriptType; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Script\Classifier\OutputClassifier; include_once "../libraries/vendor/autoload.php"; $noOfInputs = 10; $noOfOutputs = 1; include_once("html_iframe_header.php"); if ($_GET['tab'] == 'form2_tabitem1' AND $_SERVER['REQUEST_METHOD'] == 'POST') { try { $networkClass = $_POST['network']; Bitcoin::setNetwork(NetworkFactory::$networkClass()); $network = Bitcoin::getNetwork(); $ecAdapter = Bitcoin::getEcAdapter(); $privKeyFactory = new PrivateKeyFactory(); $addrCreator = new AddressCreator(); $spendTx = TransactionFactory::build(); $signItems = []; if (!is_numeric($_POST['no_of_inputs']) OR !is_numeric($_POST['no_of_outputs'])) { throw new Exception("Error in 'no_of_inputs' or 'no_of_outputs'."); } foreach(range(1,$_POST['no_of_inputs']) as $thisInput) { $utxoHash = trim($_POST["utxo_hash_{$thisInput}"]); $utxoNOutput = trim($_POST["utxo_n_{$thisInput}"]); $privkeyhex = trim($_POST["privkey_{$thisInput}"]); $utxoScript = trim($_POST["utxo_script_{$thisInput}"]); if (strlen($utxoHash)>0 AND strlen($utxoNOutput) > 0 AND strlen($privkeyhex) > 0) { $spendTx = $spendTx->input($utxoHash, $utxoNOutput); $signItems[] = [$privkeyhex, $utxoScript]; } else { throw new Exception("Error in 'input#{$thisInput}'."); } } foreach(range(1,$_POST['no_of_outputs']) as $thisOutput) { $address = trim($_POST["address_{$thisOutput}"]); $amount = trim($_POST["amount_{$thisOutput}"]); if (!strlen($address) or !strlen($amount)) { throw new Exception("Error in 'output#{$thisOutput}'."); } if (ctype_xdigit($address)) {//hex $recipient = ScriptFactory::fromHex($address); $decodeScript = (new OutputClassifier())->decode($recipient); if ($decodeScript->getType() != ScriptType::MULTISIG) { throw new Exception("Invalid P2MS output in 'output#{$thisOutput}' (Check scriptPubKey)."); } $spendTx = $spendTx->output($amount, $recipient); } else { $recipient = $addrCreator->fromString($address); $decodeScript = (new OutputClassifier())->decode($recipient->getScriptPubKey()); if ($decodeScript->getType() != ScriptType::P2SH) { throw new Exception("Invalid P2SH addresss in 'output#{$thisOutput}' (Check scriptPubKey)."); } $spendTx = $spendTx->payToAddress($amount, $recipient); } } $thisTx = $spendTx->get(); $signer = new Signer($thisTx, $ecAdapter); foreach($signItems as $nIn=>$signItem) { $privateKey = $privKeyFactory->fromHexCompressed($signItem[0]); $scriptPubKey = ScriptFactory::fromHex($signItem[1]); $txOutput = new TransactionOutput(0, $scriptPubKey ); $signer = $signer->sign($nIn, $privateKey, $txOutput); } ?> <div class="alert alert-success"> <h6 class="mt-3">Final TX Hex</h6> <textarea class="form-control" rows="5" id="comment" readonly><?php echo $signer->get()->getHex();?></textarea> </div> <?php } catch (Exception $e) { $errmsg .= "Problem found. " . $e->getMessage(); } } if ($errmsg) { ?> <div class="alert alert-danger"> <strong>Error!</strong> <?php echo $errmsg?> </div> <?php } ?> <form action='?tab=form2_tabitem1#hashtag2' method='post'> <div class="form-group"> <label for="network">Network: </label> <select name="network" id="network" class="form-control"> <?php $networks = get_class_methods(new NetworkFactory()); foreach($networks as $network) { echo "<option value='{$network}'".($network == $_POST['network'] ? " selected": "").">{$network}</option>"; } ?> </select> </div> <div class="row"> <div class="col-sm-6"> <div class="form-row"> <div class="form-group col"> <label for="no_of_inputs">Inputs: </label> <select class="form-control" style="width:auto;" id="no_of_inputs" name='no_of_inputs' onchange=" var self = $(this); var thisvalue = self.val(); var form = self.closest('form'); $('div[id^=row_input_]',form).hide(); for(var i=1; i<= thisvalue; i++) { $('div[id=row_input_'+ i + ']',form).show(); } "> <?php foreach(range(1,$noOfInputs) as $thisInput) { echo "<option value='{$thisInput}'".($thisInput == $_POST['no_of_inputs'] ? " selected": "").">{$thisInput}</option>"; } ?> </select> </div> </div> <?php $selected_n_inputs = is_numeric($_POST['no_of_inputs']) ? $_POST['no_of_inputs'] : 1; foreach(range(1,$noOfInputs) as $thisInput) { ?> <div class="form-row" id='row_input_<?php echo $thisInput?>' style="<?php echo ($thisInput > $selected_n_inputs) ? "display:none" : "display:;"?>"> <div class="form-group col-sm-1"> #<?php echo $thisInput?> </div> <div class="form-group col-sm-3"> <input class="form-control" title="UTXO Tx Hash" placeholder='UTXO Tx Hash' type='text' name='utxo_hash_<?php echo $thisInput?>' value='<?php echo $_POST["utxo_hash_{$thisInput}"]?>'> </div> <div class="form-group col-sm-1"> <input class="form-control" title="UTXO N Output" placeholder='N' type='text' name='utxo_n_<?php echo $thisInput?>' value='<?php echo $_POST["utxo_n_{$thisInput}"]?>'> </div> <div class="form-group col-sm-3"> <input class="form-control" title="UTXO ScriptPubKey" placeholder='UTXO ScriptPubKey' type='text' name='utxo_script_<?php echo $thisInput?>' value='<?php echo $_POST["utxo_script_{$thisInput}"]?>'> </div> <div class="form-group col-sm-4"> <input class="form-control" title="Private Key Hex, for signing purpose." placeholder='Private Key Hex' type='text' name='privkey_<?php echo $thisInput?>' value='<?php echo $_GET['tab'] == 'form2_tabitem1' ?$_POST["privkey_{$thisInput}"] : ''?>'> </div> </div> <?php } ?> </div> <div class="col-sm-6"> <div class="form-row"> <div class="form-group col"> <label for="no_of_outputs">Outputs:</label> <select class="form-control" id="no_of_outputs" name='no_of_outputs' style='width:auto;' onchange=" var self = $(this); var thisvalue = self.val(); var form = self.closest('form'); $('div[id^=row_output_]',form).hide(); for(var i=1; i<= thisvalue; i++) { $('div[id=row_output_'+ i + ']',form).show(); } "> <?php foreach(range(1,$noOfOutputs) as $thisOutput) { echo "<option value='{$thisOutput}'".($thisOutput == $_POST['no_of_outputs'] ? " selected": "").">{$thisOutput}</option>"; } ?> </select> </div> </div> <?php $selected_n_outputs = is_numeric($_POST['no_of_outputs']) ? $_POST['no_of_outputs'] : 1; foreach(range(1,$noOfOutputs) as $thisOutput) { ?> <div class="form-row" id='row_output_<?php echo $thisOutput?>' style="<?php echo ($thisOutput > $selected_n_outputs) ? "display:none" : "display:;"?>"> <div class="form-group col-sm-1"> #<?php echo $thisOutput?> </div> <div class="form-group col-sm-6"> <input class="form-control" title='P2SH.Multisig Address / P2MS ScriptPubKey' placeholder='P2SH.Multisig Address / P2MS ScriptPubKey' type='text' name='address_<?php echo $thisOutput?>' value='<?php echo $_POST["address_{$thisOutput}"]?>'> </div> <div class="form-group col-sm-5"> <input class="form-control" placeholder='Amount' type='text' name='amount_<?php echo $thisOutput?>' value='<?php echo $_POST["amount_{$thisOutput}"]?>'> </div> </div> <?php } ?> </div> </div> <input type='submit' class="btn btn-success btn-block"/> </form> <?php include_once("html_iframe_footer.php");
<?php use BitWasp\Bitcoin\Bitcoin; use BitWasp\Bitcoin\Network\NetworkFactory; use BitWasp\Buffertools\Buffer; use BitWasp\Bitcoin\Key\Factory\PublicKeyFactory; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Script\P2shScript; use BitWasp\Bitcoin\Script\Opcodes; include_once "../libraries/vendor/autoload.php"; $M_N_Range = range(1,15); include_once("html_iframe_header.php"); if ($_SERVER['REQUEST_METHOD'] == 'POST') { try { $networkClass = $_POST['network']; Bitcoin::setNetwork(NetworkFactory::$networkClass()); $network = Bitcoin::getNetwork(); $pubKeys = []; $publicKeyFactory = new PublicKeyFactory(); if (!in_array($_POST['reqsig'], $M_N_Range)) { throw new Exception("'Required Signature' value is not valid."); } else { foreach($_POST['pubkey'] as $pubkey_hex) { if (strlen($pubkey_hex) > 0 AND !ctype_xdigit($pubkey_hex)) { throw new Exception("Public key must be hex."); } if (strlen($pubkey_hex) > 0 AND ctype_xdigit($pubkey_hex)) { $validPubKeys[] = $publicKeyFactory->fromHex($pubkey_hex);; } } } if ($_POST['reqsig'] > count($validPubKeys)) { throw new Exception("Required signature value should not exceed number of public key."); } // make a n-of-m multisignature script $multisig = ScriptFactory::scriptPubKey()->multisig($_POST['reqsig'], $validPubKeys, $sort = false); // use the P2shScript 'decorator' to 'extend' script with extra functions relevant to a P2SH script $redeemScript = new P2shScript($multisig); $scriptPubKey = $redeemScript->getOutputScript(); $opcodes = $scriptPubKey->getOpcodes(); ?> <div class="table-responsive"> <h6 class="mt-3">P2SH.Multisig</h6> <table border=0 class='table'> <tr style='background-color:#f0f0f0'><td>Base58 address</td><td><?php echo $redeemScript->getAddress()->getAddress();?></td></tr> <tr><td>Redeem Script Hex </td><td><?php echo $redeemScript->getHex();?></td></tr> <tr><td>Redeem Script Asm</td> <td> <?php foreach( $redeemScript->getScriptParser()->decode() as $operation ) { if ($operation->isPush()) { echo htmlentities("<{$operation->getData()->getHex()}> "); } else { echo $opcodes->getOp($operation->getOp()) . " " ; } } ?> </td> </tr> <tr><td>Redeem Script Hash Hex</td><td><?php echo $redeemScript->getScriptHash()->getHex();?></td></tr> <tr style='background-color:#f0f0f0'><td>ScriptPubKey Hex </td><td><?php echo $scriptPubKey->getHex()?></td></tr> <tr style='background-color:#f0f0f0'><td>ScriptPubKey Asm</td> <td> <?php foreach( $scriptPubKey->getScriptParser()->decode() as $operation ) { if ($operation->isPush()) { echo htmlentities("<{$operation->getData()->getHex()}> "); } else { echo $opcodes->getOp($operation->getOp()) . " " ; } } ?> </td> </tr> </table> <?php if (@count($validPubKeys) <= 3) { ?> <h6 class="mt-3">P2MS</h6> <table border=0 class='table'> <tr><td>ScriptPubKey Hex </td><td><?php echo $redeemScript->getHex();?></td></tr> <tr><td>ScriptPubKey Asm</td> <td> <?php foreach( $redeemScript->getScriptParser()->decode() as $operation ) { if ($operation->isPush()) { echo htmlentities("<{$operation->getData()->getHex()}> "); } else { echo $opcodes->getOp($operation->getOp()) . " " ; } } ?> </td> </tr> </table> <?php } ?> </div> <?php } catch (Exception $e) { $errmsg .= "Problem found. " . $e->getMessage(); } } if ($errmsg) { ?> <div class="alert alert-danger"> <strong>Error!</strong> <?php echo $errmsg?> </div> <?php } ?> <form action='' method='post'> <div class="form-group"> <label for="network">Network:</label> <select id="network" name="network" class="form-control" > <?php $networks = get_class_methods(new NetworkFactory()); foreach($networks as $network) { echo "<option value='{$network}'".($network == $_POST['network'] ? " selected": "").">{$network}</option>"; } ?> </select> </div> <div class="form-group"> <label for="pubkey">Public Key Hex:</label> <div class="input-group mb-3"> <input class="form-control" type='text' name='pubkey[]' id='pubkey' value='<?php echo $_POST['pubkey'][0]?>'> <div class="input-group-append"> <input class="btn btn-success" type="button" value="+" onclick="$('#multisig-pubkey-holder').find('div').first().clone().appendTo('#multisig-pubkey-holder')"/> </div> </div> </div> <?php $displayPublickey = count($_POST['pubkey'])-1; $displayPublickey = max(1, $displayPublickey); ?> <div id="multisig-pubkey-holder" class="form-group"> <?php foreach(range(1, $displayPublickey) as $n) { ?> <div class="input-group mb-3"> <input class="form-control" type='text' name='pubkey[]' value='<?php echo $_POST['pubkey'][$n]?>'> <div class="input-group-append"> <input class="btn btn-success" type="button" value=" - " onclick=" var length = $(this).closest('#multisig-pubkey-holder').find('input[value=\' - \']').length; if (length > 1) { $(this).parent('div').parent('div').remove(); } else { alert('At least 2 public keys are required'); } "/> </div> </div> <?Php } ?> </div> <div class="form-group"> <label for="reqsig">Required Signature To Spend:</label> <select id="reqsig" name="reqsig" class="form-control" > <?php foreach($M_N_Range as $k) { echo "<option value='{$k}'".($k == $_POST['reqsig'] ? " selected": "").">{$k}</option>"; } ?> </select> </div> <input type='submit' class="btn btn-success btn-block"/> </form> <?php include_once("html_iframe_footer.php");