/** * @param NetworkInterface $network * @param PrivateKeyInterface $privateKey * @return string */ public function serialize(NetworkInterface $network, PrivateKeyInterface $privateKey) { $serialized = Buffertools::concat(Buffer::hex($network->getPrivByte()), $this->hexSerializer->serialize($privateKey)); if ($privateKey->isCompressed()) { $serialized = Buffertools::concat($serialized, new Buffer("", 1)); } return Base58::encodeCheck($serialized); }
/** * @expectedException \RuntimeException * @expectedExceptionMessage Invalid packet checksum */ public function testInvalidChecksum() { $v = '60002'; $services = Buffer::hex('0000000000000001'); $time = '123456789'; $recipient = new NetworkAddress(Buffer::hex('0000000000000001'), '10.0.0.1', '8332'); $sender = new NetworkAddress(Buffer::hex('0000000000000001'), '10.0.0.2', '8332'); $userAgent = new Buffer("/Satoshi:0.7.2/"); $lastBlock = '212672'; $random = new Random(); $nonce = $random->bytes(8)->getInt(); $version = new Version($v, $services, $time, $recipient, $sender, $nonce, $userAgent, $lastBlock, true); $msg = $version->getNetworkMessage(); $realBuffer = $msg->getBuffer(); $invalid = Buffertools::concat(Buffertools::concat($realBuffer->slice(0, 20), Buffer::hex('00000000')), $realBuffer->slice(24)); $serializer = new NetworkMessageSerializer(Bitcoin::getDefaultNetwork()); $serializer->parse($invalid); }
/** * Traverse the Merkle Tree hashes and extract those which have a matching bit. * * @param int $height * @param int $position * @param int $nBitsUsed * @param int $nHashUsed * @param BufferInterface[] $vMatch * @return BufferInterface */ public function traverseAndExtract($height, $position, &$nBitsUsed, &$nHashUsed, &$vMatch) { if ($nBitsUsed >= count($this->vFlagBits)) { $this->fBad = true; return new Buffer(); } $parent = $this->vFlagBits[$nBitsUsed++]; if (0 === $height || !$parent) { if ($nHashUsed >= count($this->vHashes)) { $this->fBad = true; return new Buffer(); } $hash = $this->vHashes[$nHashUsed++]; if ($height === 0 && $parent) { $vMatch[] = $hash->flip(); } return $hash; } else { $left = $this->traverseAndExtract($height - 1, $position * 2, $nBitsUsed, $nHashUsed, $vMatch); if ($position * 2 + 1 < $this->calcTreeWidth($height - 1)) { $right = $this->traverseAndExtract($height - 1, $position * 2 + 1, $nBitsUsed, $nHashUsed, $vMatch); if ($right === $left) { $this->fBad = true; } } else { $right = $left; } return Hash::sha256d(Buffertools::concat($left, $right)); } }
/** * @param NetworkMessage $object * @return Buffer */ public function serialize(NetworkMessage $object) { $payload = $object->getPayload()->getBuffer(); $command = str_pad(unpack("H*", $object->getCommand())[1], 24, '0', STR_PAD_RIGHT); $header = $this->getHeaderTemplate()->write([Buffer::hex($this->network->getNetMagicBytes()), Buffer::hex($command), $payload->getSize(), $object->getChecksum()]); return Buffertools::concat($header, $payload); }
/** * @param BlockInterface $block * @return \BitWasp\Buffertools\Buffer */ public function serialize(BlockInterface $block) { return Buffertools::concat($this->headerSerializer->serialize($block->getHeader()), $this->getTxsTemplate()->write([$block->getTransactions()->all()])); }
public function testConcat() { $a = Buffer::hex("1100"); $b = Buffer::hex("0011"); $c = Buffer::hex("11", 2); $this->assertEquals("11000011", Buffertools::concat($a, $b)->getHex()); $this->assertEquals("00111100", Buffertools::concat($b, $a)->getHex()); $this->assertEquals("11000011", Buffertools::concat($a, $c)->getHex()); $this->assertEquals("00111100", Buffertools::concat($c, $a)->getHex()); }
/** * @param GetBlocks $msg * @return \BitWasp\Buffertools\Buffer */ public function serialize(GetBlocks $msg) { return Buffertools::concat($this->getVersionTemplate()->write([$msg->getVersion()]), $this->locator->serialize($msg->getLocator())); }
/** * Encode the given data in base58, with a checksum to check integrity. * * @param BufferInterface $data * @return string * @throws \Exception */ public static function encodeCheck(BufferInterface $data) { return self::encode(Buffertools::concat($data, self::checksum($data))); }
/** * 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)))); }
/** * @return Buffer */ public function getMPK() { $math = $this->ecAdapter->getMath(); $point = $this->getMasterPublicKey()->getPoint(); return Buffertools::concat(Buffer::hex($math->decHex($point->getX()), 32), Buffer::hex($math->decHex($point->getY()), 32)); }
/** * Create a buffer containing data to be hashed hashed to yield the child offset * * @param integer|string $sequence * @return Buffer * @throws \Exception */ public function getHmacSeed($sequence) { $hardened = $this->ecAdapter->getMath()->getBinaryMath()->isNegative($sequence, 32); if ($hardened) { if ($this->isPrivate() === false) { throw new \Exception("Can't derive a hardened key without the private key"); } $buffer = Buffertools::concat(new Buffer(""), $this->getPrivateKey()->getBuffer()); } else { $buffer = $this->getPublicKey()->getBuffer(); } return (new Parser($buffer))->writeBytes(4, Buffer::int($sequence, 4))->getBuffer(); }
/** * @param TransactionInputInterface $input * @return Buffer */ public function serialize(TransactionInputInterface $input) { return Buffertools::concat($this->outpointSerializer->serialize($input->getOutPoint()), $this->getInputTemplate()->write([$input->getScript()->getBuffer(), $input->getSequence()])); }
/** * @param FilteredBlock $merkleBlock * @return \BitWasp\Buffertools\BufferInterface */ public function serialize(FilteredBlock $merkleBlock) { return Buffertools::concat($this->headerSerializer->serialize($merkleBlock->getHeader()), $this->treeSerializer->serialize($merkleBlock->getPartialTree())); }
/** * @param Alert $alert * @return \BitWasp\Buffertools\Buffer */ public function serialize(Alert $alert) { $sig = $alert->getSignature(); return Buffertools::concat($alert->getDetail()->getBuffer(), $this->getSigTemplate()->write([$sig->getR(), $sig->getS()])); }
/** * @param Alert $alert * @return \BitWasp\Buffertools\Buffer */ public function serialize(Alert $alert) { $detail = $alert->getDetail()->getBuffer(); $sig = $this->getSigBuf()->write([$alert->getSignature()->getBuffer()]); return Buffertools::concat($detail, $sig); }