/**
  * @param TransactionSignature $txSig
  * @return \BitWasp\Buffertools\Buffer
  */
 public function serialize(TransactionSignature $txSig)
 {
     $sig = $this->sigSerializer->serialize($txSig->getSignature());
     $parser = new Parser($sig->getHex());
     $parser->writeBytes(1, Buffer::int($txSig->getHashType(), 1));
     $buffer = $parser->getBuffer();
     return $buffer;
 }
Beispiel #2
0
 /**
  * @return \BitWasp\Bitcoin\Block\BlockInterface
  */
 public function getGenesisBlock()
 {
     $timestamp = new Buffer('The Times 03/Jan/2009 Chancellor on brink of second bailout for banks', null, $this->math);
     $publicKey = Buffer::hex('04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f', null, $this->math);
     $inputScript = ScriptFactory::sequence([Buffer::int('486604799', 4, $this->math)->flip(), Buffer::int('4', null, $this->math), $timestamp]);
     $outputScript = ScriptFactory::sequence([$publicKey, Opcodes::OP_CHECKSIG]);
     return new Block($this->math, $this->getGenesisBlockHeader(), new TransactionCollection([(new TxBuilder())->version('1')->input(new Buffer('', 32), 4294967295.0, $inputScript)->output(5000000000.0, $outputScript)->locktime(0)->get()]));
 }
 /**
  * @param BloomFilter $filter
  * @return BufferInterface
  */
 public function serialize(BloomFilter $filter)
 {
     $math = new Math();
     $vBuf = [];
     foreach ($filter->getData() as $i) {
         $vBuf[] = Buffer::int($i, 1, $math);
     }
     return $this->getTemplate()->write([$vBuf, $filter->getNumHashFuncs(), $filter->getTweak(), (string) $filter->getFlags()]);
 }
 /**
  * @param PublicKey $publicKey
  * @return Buffer
  */
 private function doSerialize(PublicKey $publicKey)
 {
     $math = $this->ecAdapter->getMath();
     $point = $publicKey->getPoint();
     $compressed = $publicKey->isCompressed();
     $parser = new Parser('', $math);
     $parser->writeBytes(1, $this->getPrefix($compressed, $point));
     $compressed ? $parser->writeBytes(32, Buffer::int($point->getX(), null, $math)) : $parser->writeBytes(32, Buffer::int($point->getX(), null, $math))->writeBytes(32, Buffer::int($point->getY(), null, $math));
     return $parser->getBuffer();
 }
Beispiel #5
0
 /**
  * @param EcAdapter $ecAdapter
  * @param $int
  * @param bool $compressed
  * @throws InvalidPrivateKey
  */
 public function __construct(EcAdapter $ecAdapter, $int, $compressed = false)
 {
     if (false === $ecAdapter->validatePrivateKey(Buffer::int($int, 32, $ecAdapter->getMath()))) {
         throw new InvalidPrivateKey('Invalid private key - must be less than curve order.');
     }
     if (false === is_bool($compressed)) {
         throw new \InvalidArgumentException('PrivateKey: Compressed argument must be a boolean');
     }
     $this->ecAdapter = $ecAdapter;
     $this->secretMultiplier = $int;
     $this->compressed = $compressed;
 }
 /**
  * @param AlertDetail $detail
  * @return \BitWasp\Buffertools\Buffer
  */
 public function serialize(AlertDetail $detail)
 {
     $setCancels = [];
     foreach ($detail->getSetCancel() as $toCancel) {
         $t = new Parser();
         $setCancels[] = $t->writeBytes(4, Buffer::int($toCancel), true)->getBuffer();
     }
     $setSubVers = [];
     foreach ($detail->getSetSubVer() as $subVer) {
         $t = new Parser();
         $setSubVers[] = $t->writeBytes(4, Buffer::int($subVer), true)->getBuffer();
     }
     return $this->getTemplate()->write([$detail->getVersion(), $detail->getRelayUntil(), $detail->getExpiration(), $detail->getId(), $detail->getCancel(), $setCancels, $detail->getMinVer(), $detail->getMaxVer(), $setSubVers, $detail->getPriority(), $detail->getComment(), $detail->getStatusBar()]);
 }
 /**
  * @param array $bits
  * @return array
  */
 private function bitsToBuffers(array $bits)
 {
     $math = Bitcoin::getMath();
     $vBuffers = str_split(str_pad('', (count($bits) + 7) / 8, '0', STR_PAD_LEFT));
     $nBits = count($bits);
     for ($p = 0; $p < $nBits; $p++) {
         $index = (int) floor($p / 8);
         $vBuffers[$index] |= $bits[$p] << $p % 8;
     }
     foreach ($vBuffers as &$value) {
         $value = Buffer::int($value, null, $math);
     }
     unset($value);
     return $vBuffers;
 }
 /**
  * Push data into the stack.
  *
  * @param $data
  * @return $this
  * @throws \Exception
  */
 public function push(Buffer $data)
 {
     $length = $data->getSize();
     $parsed = new Parser('', $this->math);
     /** Note that larger integers are serialized without flipping bits - Big endian */
     if ($length < $this->opcodes->getOpByName('OP_PUSHDATA1')) {
         $varInt = Buffertools::numToVarInt($length);
         $data = new Buffer($varInt->getBinary() . $data->getBinary(), null, $this->math);
         $parsed->writeBytes($data->getSize(), $data);
     } else {
         if ($length <= 0xff) {
             $lengthSize = 1;
         } elseif ($length <= 0xffff) {
             $lengthSize = 2;
         } else {
             $lengthSize = 4;
         }
         $op = $this->opcodes->getOpByName('OP_PUSHDATA' . $lengthSize);
         $parsed->writeBytes(1, Buffer::int($op))->writeBytes($lengthSize, Buffer::int($length), true)->writeBytes($length, $data);
     }
     $this->script .= $parsed->getBuffer()->getBinary();
     return $this;
 }
 /**
  * @dataProvider IntVectors
  */
 public function testIntConstruct($int, $size, $expectedHex, $math)
 {
     $buffer = Buffer::int($int, $size, $math);
     $this->assertEquals($expectedHex, $buffer->getHex());
 }
Beispiel #10
0
 /**
  * Calculate the hash of the current transaction, when you are looking to
  * spend $txOut, and are signing $inputToSign. The SigHashType defaults to
  * SIGHASH_ALL, though SIGHASH_SINGLE, SIGHASH_NONE, SIGHASH_ANYONECANPAY
  * can be used.
  *
  * @param ScriptInterface $txOutScript
  * @param int $inputToSign
  * @param int $sighashType
  * @return BufferInterface
  * @throws \Exception
  */
 public function calculate(ScriptInterface $txOutScript, $inputToSign, $sighashType = SigHash::ALL)
 {
     $math = Bitcoin::getMath();
     $tx = new TxMutator($this->transaction);
     $inputs = $tx->inputsMutator();
     $outputs = $tx->outputsMutator();
     // Default SIGHASH_ALL procedure: null all input scripts
     foreach ($inputs as $input) {
         $input->script(new Script());
     }
     $inputs[$inputToSign]->script($txOutScript);
     if ($math->cmp($math->bitwiseAnd($sighashType, 31), SigHash::NONE) === 0) {
         // Set outputs to empty vector, and set sequence number of inputs to 0.
         $outputs->null();
         // Let the others update at will. Set sequence of inputs we're not signing to 0.
         foreach ($inputs as $i => $input) {
             if ($i !== $inputToSign) {
                 $input->sequence(0);
             }
         }
     } elseif ($math->cmp($math->bitwiseAnd($sighashType, 31), SigHash::SINGLE) === 0) {
         // Resize output array to $inputToSign + 1, set remaining scripts to null,
         // and set sequence's to zero.
         $nOutput = $inputToSign;
         if ($nOutput >= $this->nOutputs) {
             return Buffer::hex('0100000000000000000000000000000000000000000000000000000000000000', 32, $math);
         }
         // Resize, set to null
         $outputs->slice(0, $nOutput + 1);
         for ($i = 0; $i < $nOutput; $i++) {
             $outputs[$i]->null();
         }
         // Let the others update at will. Set sequence of inputs we're not signing to 0
         foreach ($inputs as $i => $input) {
             if ($i !== $inputToSign) {
                 $input->sequence(0);
             }
         }
     }
     // This can happen regardless of whether it's ALL, NONE, or SINGLE
     if ($math->cmp($math->bitwiseAnd($sighashType, SigHash::ANYONECANPAY), 0) > 0) {
         $input = $inputs[$inputToSign]->done();
         $inputs->null()->add($input);
     }
     return Hash::sha256d(Buffertools::concat($tx->done()->getBuffer(), Buffertools::flipBytes(Buffer::int($sighashType, 4, $math))));
 }
Beispiel #11
0
 /**
  * @param int $tweak
  * @return PrivateKey
  */
 public function tweakMul($tweak)
 {
     $adapter = $this->ecAdapter;
     $math = $adapter->getMath();
     $context = $adapter->getContext();
     $privateKey = $this->getBinary();
     // mod by reference
     $tweak = Buffer::int($tweak, 32, $math)->getBinary();
     $ret = \secp256k1_ec_privkey_tweak_mul($context, $privateKey, $tweak);
     if ($ret !== 1) {
         throw new \RuntimeException('Secp256k1 privkey tweak mul: failed');
     }
     $secret = $math->hexDec(bin2hex($privateKey));
     return $adapter->getPrivateKey($secret, $this->compressed);
 }
Beispiel #12
0
 /**
  * @param int $bytes
  * @return Buffer
  */
 public function bytes($bytes)
 {
     $integer = $this->hmac->generate($this->ecAdapter->getGenerator()->getOrder());
     return Buffer::int($integer, $bytes, $this->ecAdapter->getMath());
 }
Beispiel #13
0
 /**
  * @param Buffer $bits
  * @return Buffer
  */
 public function getTargetHash(Buffer $bits)
 {
     return Buffer::int($this->getTarget($bits), 32, $this->math);
 }
 /**
  * Derive a child key
  *
  * @param $sequence
  * @return HierarchicalKey
  * @throws \Exception
  */
 public function deriveChild($sequence)
 {
     $chain = Buffer::int($this->getChainCode(), 32, $this->ecAdapter->getMath());
     $hash = Hash::hmac('sha512', $this->getHmacSeed($sequence), $chain);
     $offset = $hash->slice(0, 32);
     $chain = $hash->slice(32);
     $key = $this->isPrivate() ? $this->getPrivateKey() : $this->getPublicKey();
     if (false === $this->ecAdapter->validatePrivateKey($offset)) {
         return $this->deriveChild($sequence + 1);
     }
     return new HierarchicalKey($this->ecAdapter, $this->getDepth() + 1, $this->getChildFingerprint(), $sequence, $chain->getInt(), $key->tweakAdd($offset->getInt()));
 }
 /**
  * @param PrivateKeyInterface $privateKey
  * @return BufferInterface
  */
 public function serialize(PrivateKeyInterface $privateKey)
 {
     return Buffer::int($privateKey->getSecretMultiplier(), 32, $this->ecAdapter->getMath());
 }
Beispiel #16
0
 /**
  * Here, we return max 2000 headers following $hash.
  * Useful for helping other nodes sync.
  * @param string $hash
  * @return array
  */
 public function fetchNextHeaders($hash)
 {
     if ($this->debug) {
         echo "db: called fetchNextHeaders ({$hash})\n";
     }
     $stmt = $this->dbh->prepare("\n            SELECT    child.version, child.prevBlock, child.merkleRoot,\n                      child.nTimestamp, child.nBits, child.nNonce, child.height\n            FROM      headerIndex AS child, headerIndex AS parent\n            WHERE     child.rgt < parent.rgt\n            AND       parent.hash = :hash\n            LIMIT     2000\n        ");
     $stmt->bindParam(':hash', $hash);
     if ($stmt->execute()) {
         $results = array();
         foreach ($stmt->fetchAll() as $row) {
             $results[] = new BlockHeader($row['version'], $row['prevBlock'], $row['merkleRoot'], $row['nTimestamp'], Buffer::int($row['nBits'], 4), $row['nNonce']);
         }
         $stmt->closeCursor();
         return $results;
     }
     throw new \RuntimeException('Failed to fetch next headers ' . $hash);
 }
Beispiel #17
0
 /**
  * @param $height
  * @return \React\Promise\Promise
  */
 public function blockGetHeader($height)
 {
     return $this->client->request('blockchain.block.get_header', [$height])->then(function (Response $response) {
         $content = $response->getResult();
         return new BlockHeader($content['version'], isset($content['prev_block_hash']) ? Buffer::hex($content['prev_block_hash'], 32) : new Buffer('', 32), Buffer::hex($content['merkle_root'], 32), $content['timestamp'], Buffer::int($content['bits'], 4, $this->math), $content['nonce']);
     });
 }
Beispiel #18
0
 /**
  * Calculate the hash of the current transaction, when you are looking to
  * spend $txOut, and are signing $inputToSign. The SigHashType defaults to
  * SIGHASH_ALL, though SIGHASH_SINGLE, SIGHASH_NONE, SIGHASH_ANYONECANPAY
  * can be used.
  *
  * @param ScriptInterface $txOutScript
  * @param int $inputToSign
  * @param int $sighashType
  * @return BufferInterface
  * @throws \Exception
  */
 public function calculate(ScriptInterface $txOutScript, $inputToSign, $sighashType = SigHash::ALL)
 {
     $sighashType = (int) $sighashType;
     $hashPrevOuts = $this->hashPrevOuts($sighashType);
     $hashSequence = $this->hashSequences($sighashType);
     $hashOutputs = $this->hashOutputs($sighashType, $inputToSign);
     $input = $this->transaction->getInput($inputToSign);
     return Hash::sha256d(new Buffer(pack("V", $this->transaction->getVersion()) . $hashPrevOuts->getBinary() . $hashSequence->getBinary() . $input->getOutPoint()->getBinary() . ScriptFactory::create()->push($txOutScript->getBuffer())->getScript()->getBinary() . Buffer::int($this->amount, 8)->flip()->getBinary() . pack("V", $input->getSequence()) . $hashOutputs->getBinary() . pack("V", $this->transaction->getLockTime()) . pack("V", $sighashType)));
 }