/** * @param Parser $parser * @return Transaction * @throws \BitWasp\Buffertools\Exceptions\ParserOutOfRange * @throws \Exception */ public function fromParser(Parser &$parser) { $parse = $this->getTemplate()->parse($parser); $version = $parse[0]; $txIns = $parse[1]; $txOuts = $parse[2]; $locktime = $parse[3]; $tx = new Transaction($version, null, null, $locktime); $tx->getInputs()->addInputs($txIns); $tx->getOutputs()->addOutputs($txOuts); return $tx; }
/** * @param TransactionInterface|null $coinbaseTx * @return Block * @throws \BitWasp\Bitcoin\Exceptions\MerkleTreeEmpty */ public function run(TransactionInterface $coinbaseTx = null) { $nonce = '0'; $maxNonce = $this->math->pow(2, 32); // Allow user supplied transactions if ($coinbaseTx == null) { $coinbaseTx = new Transaction(); $coinbaseTx->getInputs()->addInput(new TransactionInput('0000000000000000000000000000000000000000000000000000000000000000', 4294967295.0)); $coinbaseTx->getOutputs()->addOutput(new TransactionOutput(5000000000.0, $this->script)); } $inputs = $coinbaseTx->getInputs(); $found = false; $usingDiff = $this->lastBlockHeader->getBits(); $diff = new Difficulty($this->math); $target = $diff->getTarget($usingDiff); while (false === $found) { // Set coinbase script, and build Merkle tree & block header. $inputs->getInput(0)->setScript($this->getCoinbaseScriptBuf()); $transactions = new TransactionCollection(array_merge(array($coinbaseTx), $this->transactions->getTransactions())); $merkleRoot = new MerkleRoot($this->math, $transactions); $merkleHash = $merkleRoot->calculateHash(); $header = new BlockHeader($this->version, $this->lastBlockHeader->getBlockHash(), $merkleHash, $this->timestamp, $usingDiff, '0'); $t = microtime(true); // Loop through all nonces (up to 2^32). Restart after modifying extranonce. while ($this->math->cmp($header->getNonce(), $maxNonce) <= 0) { $header->setNonce($this->math->add($header->getNonce(), '1')); $hash = (new Parser())->writeBytes(32, Hash::sha256d($header->getBuffer()), true)->getBuffer(); if ($this->math->cmp($hash->getInt(), $target) <= 0) { $block = new Block($this->math, $header, $transactions); return $block; } if ($this->report && $this->math->cmp($this->math->mod($header->getNonce(), 100000), '0') == 0) { $time = microtime(true) - $t; $khash = $nonce / $time / 1000; echo "extraNonce[{$this->extraNonce}] nonce[{$nonce}] time[{$time}] khash/s[{$khash}] \n"; } } // Whenever we exceed 2^32, increment extraNonce and reset $nonce $this->extraNonce++; $nonce = '0'; } }
<?php require "../vendor/autoload.php"; use BitWasp\Bitcoin\Bitcoin; use BitWasp\Bitcoin\Key\PrivateKeyFactory; use BitWasp\Bitcoin\Script\ScriptFactory; use BitWasp\Bitcoin\Transaction\Transaction; use BitWasp\Bitcoin\Transaction\TransactionInput; use BitWasp\Bitcoin\Transaction\TransactionOutput; use BitWasp\Bitcoin\Transaction\TransactionBuilder; use BitWasp\Bitcoin\Transaction\TransactionFactory; $ecAdapter = Bitcoin::getEcAdapter(); // Two users independently create private keys. $pk1 = PrivateKeyFactory::fromHex('421c76d77563afa1914846b010bd164f395bd34c2102e5e99e0cb9cf173c1d87'); $pk2 = PrivateKeyFactory::fromHex('f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162'); // They exchange public keys, and a multisignature address is made. $redeemScript = ScriptFactory::multisig(2, [$pk1->getPublicKey(), $pk2->getPublicKey()]); $outputScript = $redeemScript->getOutputScript(); // The address is funded with a transaction (fake, for the purposes of this script). // You would do getrawtransaction normally $spendTx = new Transaction(); $spendTx->getInputs()->addInput(new TransactionInput('4141414141414141414141414141414141414141414141414141414141414141', 0)); $spendTx->getOutputs()->addOutput(new TransactionOutput(50, $outputScript)); // One party wants to spend funds. He creates a transaction spending the funding tx to his address. $builder = new TransactionBuilder($ecAdapter); $builder->spendOutput($spendTx, 0)->payToAddress($pk1->getAddress(), 50)->signInputWithKey($pk1, $outputScript, 0, $redeemScript)->signInputWithKey($pk2, $outputScript, 0, $redeemScript); $rawTx = $builder->getTransaction()->getHex(); echo "Fully signed transaction: " . $builder->getTransaction()->getHex() . "\n";