Esempio n. 1
0
 /**
  * @dataProvider generateSet
  */
 public function testPing(Ping $ping)
 {
     $this->assertInternalType('string', $ping->getNonce());
     $this->assertEquals('ping', $ping->getNetworkCommand());
     $math = new Math();
     $this->assertEquals(str_pad($math->decHex($ping->getNonce()), 16, '0', STR_PAD_LEFT), $ping->getHex());
 }
Esempio n. 2
0
 /**
  * @param callable|null $hashFunction
  * @return Buffer
  * @throws MerkleTreeEmpty
  */
 public function calculateHash(callable $hashFunction = null)
 {
     $hashFxn = $hashFunction ?: function ($value) {
         return hash('sha256', hash('sha256', $value, true), true);
     };
     $txCount = count($this->transactions);
     if ($txCount === 0) {
         // TODO: Probably necessary. Should always have a coinbase at least.
         throw new MerkleTreeEmpty('Cannot compute Merkle root of an empty tree');
     }
     if ($txCount === 1) {
         $binary = $hashFxn($this->transactions[0]->getBinary());
     } else {
         // Create a fixed size Merkle Tree
         $tree = new FixedSizeTree($txCount + $txCount % 2, $hashFxn);
         // Compute hash of each transaction
         $last = '';
         foreach ($this->transactions as $i => $transaction) {
             $last = $transaction->getBinary();
             $tree->set($i, $last);
         }
         // Check if we need to repeat the last hash (odd number of transactions)
         if (!$this->math->isEven($txCount)) {
             $tree->set($txCount, $last);
         }
         $binary = $tree->hash();
     }
     $this->setLastHash((new Buffer($binary))->flip());
     return $this->getLastHash();
 }
 /**
  * Given a sequence, get the human readable node. Ie, 0 -> 0, 0x80000000 -> 0h
  * @param $sequence
  * @return string
  */
 public function getNode($sequence)
 {
     if ($this->isHardened($sequence)) {
         $sequence = $this->math->sub($sequence, self::START_HARDENED) . 'h';
     }
     return $sequence;
 }
Esempio n. 4
0
 /**
  * @param int $ptr
  * @return Operation
  */
 private function doNext($ptr)
 {
     if ($this->math->cmp($this->position, $this->end) >= 0) {
         throw new \RuntimeException('Position exceeds end of script!');
     }
     $opCode = ord($this->data[$this->position++]);
     $pushData = $this->empty;
     $dataSize = 0;
     if ($opCode <= Opcodes::OP_PUSHDATA4) {
         if ($opCode < Opcodes::OP_PUSHDATA1) {
             $dataSize = $opCode;
         } else {
             if ($opCode === Opcodes::OP_PUSHDATA1) {
                 $dataSize = $this->unpackSize('C', 1);
             } else {
                 if ($opCode === Opcodes::OP_PUSHDATA2) {
                     $dataSize = $this->unpackSize('v', 2);
                 } else {
                     $dataSize = $this->unpackSize('V', 4);
                 }
             }
         }
         $delta = $this->end - $this->position;
         if ($dataSize === false || $delta < 0 || $delta < $dataSize) {
             throw new \RuntimeException('Failed to unpack data from Script');
         }
         if ($dataSize > 0) {
             $pushData = new Buffer(substr($this->data, $this->position, $dataSize), $dataSize, $this->math);
         }
         $this->position += $dataSize;
     }
     $this->array[$ptr] = new Operation($opCode, $pushData, $dataSize);
     return $this->array[$ptr];
 }
Esempio n. 5
0
 /**
  * @dataProvider generateSet
  */
 public function testPong(Ping $ping)
 {
     $pong = new Pong($ping->getNonce());
     $this->assertEquals('pong', $pong->getNetworkCommand());
     $this->assertTrue($ping->getNonce() == $pong->getNonce());
     $math = new Math();
     $this->assertEquals(str_pad($math->decHex($ping->getNonce()), 16, '0', STR_PAD_LEFT), $pong->getHex());
 }
Esempio n. 6
0
 /**
  * @param Math $math
  * @param TransactionInterface $transaction
  * @return int|string
  */
 public function getValueIn(Math $math, TransactionInterface $transaction)
 {
     $value = 0;
     foreach ($transaction->getInputs() as $input) {
         $value = $math->add($value, $this->fetchByInput($input)->getOutput()->getValue());
     }
     return $value;
 }
Esempio n. 7
0
 /**
  * @param ChainAccessInterface $chain
  * @param BlockIndexInterface $index
  * @param BlockIndexInterface $prevIndex
  * @param Forks $forks
  * @return $this
  */
 public function checkContextual(ChainAccessInterface $chain, BlockIndexInterface $index, BlockIndexInterface $prevIndex, Forks $forks)
 {
     $work = $this->getWorkRequired($chain, $prevIndex);
     $header = $index->getHeader();
     if ($this->math->cmp(gmp_init($header->getBits(), 10), gmp_init($work, 10)) != 0) {
         throw new \RuntimeException('Headers::CheckContextual(): invalid proof of work : ' . $header->getBits() . '? ' . $work);
     }
     if ($header->getVersion() < $forks->getMajorityVersion()) {
         echo $index->getHash()->getHex() . PHP_EOL;
         echo "Heaader: " . $header->getVersion() . "\nMajority: " . $forks->getMajorityVersion() . PHP_EOL;
         throw new \RuntimeException('Rejected version');
     }
     return $this;
 }
Esempio n. 8
0
 /**
  * @param BlockIndexInterface $prevIndex
  * @param int $timeFirstBlock
  * @return int
  */
 public function calculateNextWorkRequired(BlockIndexInterface $prevIndex, $timeFirstBlock)
 {
     $header = $prevIndex->getHeader();
     $math = $this->math;
     $timespan = $this->calculateWorkTimespan($timeFirstBlock, $header);
     $negative = false;
     $overflow = false;
     $target = $math->decodeCompact($header->getBits(), $negative, $overflow);
     $limit = $this->math->decodeCompact($this->params->powBitsLimit(), $negative, $overflow);
     $new = gmp_init(bcdiv(bcmul($target, $timespan), $this->params->powTargetTimespan()), 10);
     if ($math->cmp($new, $limit) > 0) {
         $new = $limit;
     }
     return gmp_strval($math->encodeCompact($new, false), 10);
 }
Esempio n. 9
0
 /**
  * @param UtxoView $view
  * @param TransactionInterface $tx
  * @param int $spendHeight
  * @return $this
  */
 public function checkContextualInputs(UtxoView $view, TransactionInterface $tx, $spendHeight)
 {
     $valueIn = gmp_init(0);
     for ($i = 0, $nInputs = count($tx->getInputs()); $i < $nInputs; $i++) {
         /*if ($out->isCoinbase()) {
               // todo: cb / height
               if ($spendHeight - $out->getHeight() < $this->params->coinbaseMaturityAge()) {
                   return false;
               }
           }*/
         $value = gmp_init($view->fetchByInput($tx->getInput($i))->getOutput()->getValue(), 10);
         $valueIn = $this->math->add($valueIn, $value);
         $this->consensus->checkAmount($valueIn);
     }
     $valueOut = gmp_init(0);
     foreach ($tx->getOutputs() as $output) {
         $valueOut = $this->math->add($valueOut, gmp_init($output->getValue(), 10));
         $this->consensus->checkAmount($valueOut);
     }
     if ($this->math->cmp($valueIn, $valueOut) < 0) {
         throw new \RuntimeException('Value-in is less than value-out');
     }
     $fee = $this->math->sub($valueIn, $valueOut);
     $this->consensus->checkAmount($fee);
     return $this;
 }
Esempio n. 10
0
 /**
  * @return $this
  * @throws \Exception
  */
 private function checkOpcodeCount()
 {
     if ($this->math->cmp($this->opCount, 201) > 0) {
         throw new \RuntimeException('Error: Script op code count');
     }
     return $this;
 }
 /**
  * @param Parser $parser
  * @return CompactSignature
  * @throws ParserOutOfRange
  */
 public function fromParser(Parser &$parser)
 {
     try {
         list($byte, $r, $s) = $this->getTemplate()->parse($parser);
         $recoveryFlags = $this->math->sub($byte, 27);
         if ($recoveryFlags < 0 || $recoveryFlags > 7) {
             throw new \InvalidArgumentException('invalid signature type');
         }
         $isCompressed = $this->math->bitwiseAnd($recoveryFlags, 4) != 0;
         $recoveryId = $recoveryFlags - ($isCompressed ? 4 : 0);
     } catch (ParserOutOfRange $e) {
         throw new ParserOutOfRange('Failed to extract full signature from parser');
     }
     $signature = new CompactSignature($r, $s, $recoveryId, $isCompressed);
     return $signature;
 }
Esempio n. 12
0
 /**
  * @param $opCode
  * @param Buffer $pushData
  * @return bool
  */
 public function next(&$opCode, &$pushData)
 {
     $opcodes = $this->script->getOpcodes();
     $opCode = $opcodes->getOpByName('OP_INVALIDOPCODE');
     if ($this->math->cmp($this->getPosition(), $this->getEndPos()) >= 0) {
         return false;
     }
     $opCode = $this->getNextOp();
     if ($opcodes->cmp($opCode, 'OP_PUSHDATA4') <= 0) {
         if ($opcodes->cmp($opCode, 'OP_PUSHDATA1') < 0) {
             $size = $opCode;
         } else {
             if ($opcodes->isOp($opCode, 'OP_PUSHDATA1')) {
                 $size = $this->unpackSize("C", 1);
             } else {
                 if ($opcodes->isOp($opCode, 'OP_PUSHDATA2')) {
                     $size = $this->unpackSize("v", 2);
                 } else {
                     $size = $this->unpackSize("V", 4);
                 }
             }
         }
         if ($size === false || $this->validateSize($size) === false) {
             return false;
         }
         $pushData = new Buffer(substr($this->scriptRaw, $this->ptr, $size), $size);
         $this->ptr += $size;
     }
     return true;
 }
Esempio n. 13
0
 /**
  * Convert locktime to block height tx is locked to. Doesn't convert anything
  * really, but does check the bounds of the supplied locktime.
  *
  * @param int|string $lockTime
  * @return int|string
  * @throws \Exception
  */
 public function toBlockHeight($lockTime)
 {
     if ($this->math->cmp($lockTime, self::BLOCK_MAX) > 0) {
         throw new \Exception('This locktime is out of range for a block height');
     }
     return $lockTime;
 }
Esempio n. 14
0
 /**
  * @param $height
  * @return \React\Promise\Promise
  */
 public function blockGetHeader($height)
 {
     return $this->client->request('blockchain.block.get_header', [$height])->then(function (\BitWasp\Stratum\Request\Response $response) {
         $content = $response->getResult();
         return new \BitWasp\Bitcoin\Block\BlockHeader($content['version'], @$content['prev_block_hash'], $content['merkle_root'], $content['timestamp'], Buffer::hex($this->math->decHex($content['bits'])), $content['nonce']);
     });
 }
Esempio n. 15
0
 /**
  * @return $this
  */
 private function updateProofOfWork()
 {
     if ($this->math->cmp(0, $this->math->mod($this->currentHeight(), 2016)) == 0) {
         $this->chainDiff = $this->difficulty->getDifficulty($this->chainTip()->getHeader()->getBits());
         $this->pow = new ProofOfWork($this->math, $this->difficulty, $this->chainDiff);
     }
     return $this;
 }
Esempio n. 16
0
 /**
  * @param int $minVersion
  * @param int $startHeight
  * @param int $nRequired
  * @param Index\Blocks $blocks
  * @return bool
  */
 public function isSuperMajority($minVersion, $startHeight, Index\Blocks $blocks, $nRequired)
 {
     $nFound = 0;
     $window = $this->params->majorityWindow();
     for ($i = 0; $i < $window && $nFound < $nRequired && ($index = $blocks->fetchByHeight($startHeight - $i)); $i++) {
         if ($this->math->cmp($index->getHeader()->getVersion(), $minVersion)) {
             $nFound++;
         }
     }
     return $nFound >= $nRequired;
 }
Esempio n. 17
0
 /**
  * @return int
  */
 public function getInt()
 {
     if ($this->math->cmp($this->number, self::MAX) > 0) {
         return self::MAX;
     } else {
         if ($this->math->cmp($this->number, self::MIN) < 0) {
             return self::MIN;
         }
     }
     return $this->number;
 }
Esempio n. 18
0
 /**
  * @param \BitWasp\Bitcoin\Script\Interpreter\Number $sequence
  * @return bool
  */
 private function checkSequence(Number $sequence)
 {
     $txSequence = $this->transaction->getInput($this->inputToSign)->getSequence();
     if ($this->transaction->getVersion() < 2) {
         return false;
     }
     if ($this->math->cmp($this->math->bitwiseAnd($txSequence, TransactionInputInterface::SEQUENCE_LOCKTIME_DISABLE_FLAG), 0) !== 0) {
         return 0;
     }
     $mask = $this->math->bitwiseOr(TransactionInputInterface::SEQUENCE_LOCKTIME_TYPE_FLAG, TransactionInputInterface::SEQUENCE_LOCKTIME_MASK);
     return $this->verifyLockTime($this->math->bitwiseAnd($txSequence, $mask), TransactionInputInterface::SEQUENCE_LOCKTIME_TYPE_FLAG, Number::int($this->math->bitwiseAnd($sequence->getInt(), $mask)));
 }
 /**
  * @param Peer $sender
  * @param TransactionSignatureInterface $txSig
  * @return TransactionSignatureInterface
  */
 public function fixSig(Peer $sender, TransactionSignatureInterface $txSig, &$wasMalleated = false)
 {
     $sig = $txSig->getSignature();
     if (!$this->adapter->validateSignatureElement($sig->getS(), true)) {
         $ip = $sender->getRemoteAddr()->getIp();
         if (!isset($this->violators[$ip])) {
             $this->violators[$sender->getRemoteAddr()->getIp()] = 1;
         } else {
             $this->violators[$sender->getRemoteAddr()->getIp()]++;
         }
         $wasMalleated = true;
         $this->counter++;
         $txSig = new TransactionSignature($this->adapter, new Signature($this->adapter, $sig->getR(), $this->math->sub($this->order, $sig->getS())), $txSig->getHashType());
         if (!$this->adapter->validateSignatureElement($txSig->getSignature()->getS(), true)) {
             die('failed to produce a low-s signature');
         }
     }
     return $txSig;
 }
Esempio n. 20
0
 /**
  * @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';
     }
 }
Esempio n. 21
0
 /**
  * @param ChainState $state
  * @param BlockInterface $block
  * @param Headers $headers
  * @param UtxoIdx $utxoIdx
  * @return BlockIndex
  */
 public function accept(ChainState $state, BlockInterface $block, Headers $headers, UtxoIdx $utxoIdx)
 {
     $bestBlock = $state->getLastBlock();
     if ($bestBlock->getHash() !== $block->getHeader()->getPrevBlock()) {
         throw new \RuntimeException('Blocks:accept() Block does not extend this chain!');
     }
     $index = $headers->accept($state, $block->getHeader());
     $this->blockCheck->check($block)->checkContextual($block, $bestBlock);
     //$view = $utxoIdx->fetchView($state, $block);
     $view = $this->db->fetchUtxoView($block);
     $flagP2sh = $this->consensus->scriptVerifyPayToScriptHash($bestBlock->getHeader()->getTimestamp());
     $flags = new Flags($flagP2sh ? InterpreterInterface::VERIFY_P2SH : InterpreterInterface::VERIFY_NONE);
     $nInputs = 0;
     $nFees = 0;
     $nSigOps = 0;
     $txs = $block->getTransactions();
     foreach ($block->getTransactions() as $tx) {
         $nInputs += count($tx->getInputs());
         $nSigOps += $this->blockCheck->getLegacySigOps($tx);
         if ($nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) {
             throw new \RuntimeException('Blocks::accept() - too many sigops');
         }
         if (!$tx->isCoinbase()) {
             if ($flagP2sh) {
                 $nSigOps = $this->blockCheck->getP2shSigOps($view, $tx);
                 if ($nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) {
                     throw new \RuntimeException('Blocks::accept() - too many sigops');
                 }
             }
             $fee = $this->math->sub($view->getValueIn($this->math, $tx), $tx->getValueOut());
             $nFees = $this->math->add($nFees, $fee);
             $this->blockCheck->checkInputs($view, $tx, $index->getHeight(), $flags);
         }
     }
     $this->blockCheck->checkCoinbaseSubsidy($txs[0], $nFees, $index->getHeight());
     $this->db->insertBlock($block);
     $state->updateLastBlock($index);
     return $index;
 }
Esempio n. 22
0
 /**
  * @param UtxoView $view
  * @param TransactionInterface $tx
  * @param $spendHeight
  * @return bool
  */
 public function checkContextualInputs(UtxoView $view, TransactionInterface $tx, $spendHeight)
 {
     $valueIn = 0;
     for ($i = 0; $i < count($tx->getInputs()); $i++) {
         $utxo = $view->fetchByInput($tx->getInput($i));
         /*if ($out->isCoinbase()) {
               // todo: cb / height
               if ($spendHeight - $out->getHeight() < $this->params->coinbaseMaturityAge()) {
                   return false;
               }
           }*/
         $value = $utxo->getOutput()->getValue();
         $valueIn = $this->math->add($value, $valueIn);
         if (!$this->consensus->checkAmount($valueIn) || !$this->consensus->checkAmount($value)) {
             throw new \RuntimeException('CheckAmount failed for inputs value');
         }
     }
     $valueOut = 0;
     foreach ($tx->getOutputs() as $output) {
         $valueOut = $this->math->add($output->getValue(), $valueOut);
         if (!$this->consensus->checkAmount($valueOut) || !$this->consensus->checkAmount($output->getValue())) {
             throw new \RuntimeException('CheckAmount failed for outputs value');
         }
     }
     if ($this->math->cmp($valueIn, $valueOut) < 0) {
         throw new \RuntimeException('Value-in is less than value out');
     }
     $fee = $this->math->sub($valueIn, $valueOut);
     if ($this->math->cmp($fee, 0) < 0) {
         throw new \RuntimeException('Fee is less than zero');
     }
     if (!$this->consensus->checkAmount($fee)) {
         throw new \RuntimeException('CheckAmount failed for fee');
     }
     return true;
 }
Esempio n. 23
0
 /**
  * @param BlockInterface $block
  * @param BlockData $blockData
  * @param bool $checkSignatures
  * @param bool $flags
  * @param $height
  */
 public function checkBlockData(BlockInterface $block, BlockData $blockData, $checkSignatures, $flags, $height)
 {
     $validation = new ScriptValidation($checkSignatures, $flags);
     foreach ($block->getTransactions() as $tx) {
         $blockData->nSigOps += $this->blockCheck->getLegacySigOps($tx);
         if ($blockData->nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) {
             throw new \RuntimeException('Blocks::accept() - too many sigops');
         }
         if (!$tx->isCoinbase()) {
             if ($flags & InterpreterInterface::VERIFY_P2SH) {
                 $blockData->nSigOps += $this->blockCheck->getP2shSigOps($blockData->utxoView, $tx);
                 if ($blockData->nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) {
                     throw new \RuntimeException('Blocks::accept() - too many sigops');
                 }
             }
             $blockData->nFees = $this->math->add($blockData->nFees, $blockData->utxoView->getFeePaid($this->math, $tx));
             $this->blockCheck->checkInputs($blockData->utxoView, $tx, $height, $flags, $validation);
         }
     }
     if ($validation->active() && !$validation->result()) {
         throw new \RuntimeException('ScriptValidation failed!');
     }
     $this->blockCheck->checkCoinbaseSubsidy($block->getTransaction(0), $blockData->nFees, $height);
 }
Esempio n. 24
0
 /**
  * @param int $nHashNum
  * @param BufferInterface $data
  * @return string
  */
 public function hash($nHashNum, BufferInterface $data)
 {
     return $this->math->mod(Hash::murmur3($data, $nHashNum * self::TWEAK_START + $this->nTweak & 0xffffffff)->getInt(), count($this->vFilter) * 8);
 }
Esempio n. 25
0
 /**
  * @param $opCode
  * @param ScriptStack $mainStack
  * @param ScriptStack $altStack
  * @throws \BitWasp\Bitcoin\Exceptions\ScriptStackException
  * @throws \Exception
  */
 public function op($opCode, ScriptStack $mainStack, ScriptStack $altStack)
 {
     $opCodes = $this->opCodes;
     $opName = $this->opCodes->getOp($opCode);
     $castToBool = $this->castToBool;
     if ($opName == 'OP_TOALTSTACK') {
         if ($mainStack->size() < 1) {
             throw new \Exception('Invalid stack operation OP_TOALTSTACK');
         }
         $altStack->push($mainStack->pop());
         return;
     } else {
         if ($opName == 'OP_FROMALTSTACK') {
             if ($altStack->size() < 1) {
                 throw new \Exception('Invalid alt-stack operation OP_FROMALTSTACK');
             }
             $mainStack->push($altStack->pop());
             return;
         } else {
             if ($opName == 'OP_IFDUP') {
                 // If top value not zero, duplicate it.
                 if ($mainStack->size() < 1) {
                     throw new \Exception('Invalid stack operation OP_IFDUP');
                 }
                 $vch = $mainStack->top(-1);
                 if ($castToBool($vch)) {
                     $mainStack->push($vch);
                 }
                 return;
             } else {
                 if ($opName == 'OP_DEPTH') {
                     $num = $mainStack->size();
                     $bin = Buffer::hex($this->math->decHex($num));
                     $mainStack->push($bin);
                     return;
                 } else {
                     if ($opName == 'OP_DROP') {
                         if ($mainStack->size() < 1) {
                             throw new \Exception('Invalid stack operation OP_DROP');
                         }
                         $mainStack->pop();
                         return;
                     } else {
                         if ($opName == 'OP_DUP') {
                             if ($mainStack->size() < 1) {
                                 throw new \Exception('Invalid stack operation OP_DUP');
                             }
                             $vch = $mainStack->top(-1);
                             $mainStack->push($vch);
                             return;
                         } else {
                             if ($opName == 'OP_NIP') {
                                 if ($mainStack->size() < 2) {
                                     throw new \Exception('Invalid stack operation OP_NIP');
                                 }
                                 $mainStack->erase(-2);
                                 return;
                             } else {
                                 if ($opName == 'OP_OVER') {
                                     if ($mainStack->size() < 2) {
                                         throw new \Exception('Invalid stack operation OP_OVER');
                                     }
                                     $vch = $mainStack->top(-2);
                                     $mainStack->push($vch);
                                     return;
                                 } else {
                                     if (in_array($opName, ['OP_PICK', 'OP_ROLL'])) {
                                         // cscriptnum
                                         if ($mainStack->size() < 2) {
                                             throw new \Exception('Invalid stack operation OP_PICK');
                                         }
                                         $n = $mainStack->top(-1)->getInt();
                                         $mainStack->pop();
                                         if ($this->math->cmp($n, 0) < 0 || $this->math->cmp($n, $mainStack->size()) >= 0) {
                                             throw new \Exception('Invalid stack operation OP_PICK');
                                         }
                                         $pos = $this->math->sub($this->math->sub(0, $n), 1);
                                         $vch = $mainStack->top($pos);
                                         if ($opCodes->isOp($opCode, 'OP_ROLL')) {
                                             $mainStack->erase($pos);
                                         }
                                         $mainStack->push($vch);
                                         return;
                                     } else {
                                         if ($opName == 'OP_ROT') {
                                             if ($mainStack->size() < 3) {
                                                 throw new \Exception('Invalid stack operation OP_ROT');
                                             }
                                             $mainStack->swap(-3, -2);
                                             $mainStack->swap(-2, -1);
                                             return;
                                         } else {
                                             if ($opName == 'OP_SWAP') {
                                                 if ($mainStack->size() < 2) {
                                                     throw new \Exception('Invalid stack operation OP_SWAP');
                                                 }
                                                 $mainStack->swap(-2, -1);
                                                 return;
                                             } else {
                                                 if ($opName == 'OP_TUCK') {
                                                     if ($mainStack->size() < 2) {
                                                         throw new \Exception('Invalid stack operation OP_TUCK');
                                                     }
                                                     $vch = $mainStack->top(-1);
                                                     $mainStack->insert($mainStack->end() - 2, $vch);
                                                     return;
                                                 } else {
                                                     if ($opName == 'OP_2DROP') {
                                                         if ($mainStack->size() < 2) {
                                                             throw new \Exception('Invalid stack operation OP_2DROP');
                                                         }
                                                         $mainStack->pop();
                                                         $mainStack->pop();
                                                         return;
                                                     } else {
                                                         if ($opName == 'OP_2DUP') {
                                                             if ($mainStack->size() < 2) {
                                                                 throw new \Exception('Invalid stack operation OP_2DUP');
                                                             }
                                                             $string1 = $mainStack->top(-2);
                                                             $string2 = $mainStack->top(-1);
                                                             $mainStack->push($string1);
                                                             $mainStack->push($string2);
                                                             return;
                                                         } else {
                                                             if ($opName == 'OP_3DUP') {
                                                                 if ($mainStack->size() < 3) {
                                                                     throw new \Exception('Invalid stack operation OP_3DUP');
                                                                 }
                                                                 $string1 = $mainStack->top(-3);
                                                                 $string2 = $mainStack->top(-2);
                                                                 $string3 = $mainStack->top(-1);
                                                                 $mainStack->push($string1);
                                                                 $mainStack->push($string2);
                                                                 $mainStack->push($string3);
                                                                 return;
                                                             } else {
                                                                 if ($opName == 'OP_2OVER') {
                                                                     if ($mainStack->size() < 4) {
                                                                         throw new \Exception('Invalid stack operation OP_2OVER');
                                                                     }
                                                                     $string1 = $mainStack->top(-4);
                                                                     $string2 = $mainStack->top(-3);
                                                                     $mainStack->push($string1);
                                                                     $mainStack->push($string2);
                                                                     return;
                                                                 } else {
                                                                     if ($opName == 'OP_2ROT') {
                                                                         if ($mainStack->size() < 6) {
                                                                             throw new \Exception('Invalid stack operation OP_2ROT');
                                                                         }
                                                                         $string1 = $mainStack->top(-6);
                                                                         $string2 = $mainStack->top(-5);
                                                                         $mainStack->erase(-6);
                                                                         $mainStack->erase(-5);
                                                                         $mainStack->push($string1);
                                                                         $mainStack->push($string2);
                                                                         return;
                                                                     } else {
                                                                         if ($opName == 'OP_2SWAP') {
                                                                             if ($mainStack->size() < 4) {
                                                                                 throw new \Exception('Invalid stack operation OP_2SWAP');
                                                                             }
                                                                             $mainStack->swap(-3, -1);
                                                                             $mainStack->swap(-4, -2);
                                                                             return;
                                                                         }
                                                                     }
                                                                 }
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     throw new \Exception('Opcode not found');
 }
Esempio n. 26
0
 /**
  * @param Math $math
  * @param TransactionInterface $tx
  * @return \GMP
  */
 public function getFeePaid(Math $math, TransactionInterface $tx)
 {
     return $math->sub($this->getValueIn($math, $tx), gmp_init($tx->getValueOut()));
 }
Esempio n. 27
0
 /**
  * @param Buffer $bits
  * @return int|string
  */
 public function getWork(Buffer $bits)
 {
     return bcdiv($this->math->pow(2, 256), $this->getTarget($bits));
 }
Esempio n. 28
0
#!/usr/bin/php
<?php 
require_once __DIR__ . "/../vendor/autoload.php";
use BitWasp\Bitcoin\Address\AddressFactory;
use BitWasp\Bitcoin\Rpc\RpcFactory;
use BitWasp\Bitcoin\Chain\Difficulty;
use BitWasp\Bitcoin\Math\Math;
use BitWasp\Bitcoin\Network\NetworkFactory;
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Script\OutputScriptFactory;
use BitWasp\Bitcoin\Script\ScriptFactory;
use BitWasp\Buffertools\Buffer;
use willgriffin\MariaInterface\MariaInterface;
$configFile = count($argv) > 1 ? $argv[1] : false;
$x = count($argv) > 2 ? intval($argv[2]) : 1;
$math = new Math();
$difficulty = new Difficulty($math);
if (file_exists($configFile)) {
    $config = (object) parse_ini_file($configFile);
    //$currency = Main::getCurrency($currencyName);
    $db = new MariaInterface(["host" => $config->dbhost, "user" => $config->dbuser, "pass" => $config->dbpass, "port" => $config->dbport, "name" => $config->dbname]);
    $bitcoind = RpcFactory::bitcoind($config->rpchost, $config->rpcport, $config->rpcuser, $config->rpcpass);
    $network = NetworkFactory::create($config->magic_byte, $config->magic_p2sh_byte, $config->private_key_byte)->setHDPubByte($config->hd_pub_byte)->setHDPrivByte($config->hd_priv_byte)->setNetMagicBytes($config->net_magic_bytes);
    Bitcoin::setNetwork($network);
    $nextBlockHash = $bitcoind->getblockhash($x);
    do {
        echo "Block {$x}\n";
        $blockhash = $nextBlockHash;
        $block = $bitcoind->getblock($blockhash);
        $blockHeader = $block->getHeader();
        $blockBits = $blockHeader->getBits();
Esempio n. 29
0
 /**
  * @return int|string
  */
 public function getMaxTxSigOps()
 {
     return $this->math->div($this->getMaxBlockSigOps(), 5);
 }
Esempio n. 30
0
 /**
  * @param BufferInterface $hash
  * @param BlockIndexInterface $prevIndex
  * @param BlockHeaderInterface $header
  * @return BlockIndex
  */
 public function getNextIndex(BufferInterface $hash, BlockIndexInterface $prevIndex, BlockHeaderInterface $header)
 {
     return new BlockIndex($hash, $prevIndex->getHeight() + 1, $this->math->toString($this->math->add($this->proofOfWork->getWork($header->getBits()), gmp_init($prevIndex->getWork()))), $header);
 }