/** * @param Parser $parser * @return PrivateKey */ public function fromParser(Parser &$parser) { $bytes = $parser->readBytes(32); $multiplier = $bytes->getInt(); $privateKey = PrivateKeyFactory::fromInt($multiplier, false, $this->ecAdapter); return $privateKey; }
/** * @param string|BufferInterface $data * @return \BitWasp\Bitcoin\Transaction\TransactionInterface */ public function parse($data) { $parser = new Parser($data); $buffer = $parser->getBuffer(); $parsed = $this->txSerializer->parse($buffer); $this->storage->attach($parsed, $buffer); return $parsed; }
/** * @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; }
/** * @param BlockInterface $block * @return \BitWasp\Buffertools\BufferInterface */ public function serialize(BlockInterface $block) { $buffer = $block->getBuffer(); $size = $buffer->getSize(); $data = new Parser($this->getHeaderTemplate()->write([Buffer::hex($this->network->getNetMagicBytes()), $size])); $data->writeBytes($size, $buffer); return $data->getBuffer(); }
/** * @param \BitWasp\Bitcoin\Signature\TransactionSignature $txSig * @return \BitWasp\Buffertools\Buffer */ public function serialize(\BitWasp\Bitcoin\Signature\TransactionSignature $txSig) { $sig = $this->sigSerializer->serialize($txSig->getSignature()); $parser = new Parser($sig->getHex()); $parser->writeInt(1, $txSig->getHashType()); $buffer = $parser->getBuffer(); return $buffer; }
/** * @param Parser $parser * @return Buffer * @throws \BitWasp\Buffertools\Exceptions\ParserOutOfRange */ public function read(Parser &$parser) { $bits = $this->readBits($parser->readBytes($this->length)); if (!$this->isBigEndian()) { $bits = $this->flipBits($bits); } return Buffer::hex(str_pad($this->getMath()->baseConvert($bits, 2, 16), $this->length * 2, '0', STR_PAD_LEFT), $this->length, $this->getMath()); }
/** * @param Parser $parser * @return int|string * @throws \BitWasp\Buffertools\Exceptions\ParserOutOfRange * @throws \Exception */ public function readBits(Parser &$parser) { $math = $this->getMath(); $bitSize = $this->getBitSize(); $bits = str_pad($math->baseConvert($parser->readBytes($bitSize / 8)->getHex(), 16, 2), $bitSize, '0', STR_PAD_LEFT); $integer = $math->baseConvert($this->isBigEndian() ? $bits : $this->flipBits($bits), 2, 10); return $integer; }
/** * @param PublicKeyInterface $publicKey * @return Buffer */ public function serialize(PublicKeyInterface $publicKey) { $point = $publicKey->getPoint(); $parser = new Parser(); $parser->writeBytes(1, $this->getPrefix($publicKey->isCompressed(), $point)); $math = $this->ecAdapter->getMath(); $publicKey->isCompressed() ? $parser->writeBytes(32, $math->decHex($point->getX())) : $parser->writeBytes(32, $math->decHex($point->getX()))->writeBytes(32, $math->decHex($point->getY())); return $parser->getBuffer(); }
/** * @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(); }
/** * @param Headers $msg * @return \BitWasp\Buffertools\Buffer */ public function serialize(Headers $msg) { $headers = []; $null = new Buffer(""); foreach ($msg->getHeaders() as $header) { $temp = new Parser($header->getBuffer()); $temp->writeBytes(1, $null); $headers[] = $temp->getBuffer(); } return $this->getTemplate()->write([$headers]); }
/** * @param Parser $parser * @return array|OutPointInterface */ public function fromParser(Parser $parser) { $buffer = $parser->getBuffer(); if ($buffer->getSize() > 36) { $buffer = $buffer->slice(0, 36); if (isset($this->cachedStr[$buffer->getBinary()])) { $this->cached++; return $this->cachedStr[$buffer->getBinary()]; } } $parsed = $this->serializer->fromParser($parser); $this->parse++; return $parsed; }
/** * @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 Parser $parser * @return Ipv4|Ipv6|Onion * @throws \BitWasp\Buffertools\Exceptions\ParserOutOfRange * @throws \Exception */ public function fromParser(Parser $parser) { $buffer = $parser->readBytes(16); $binary = $buffer->getBinary(); if (Onion::MAGIC === substr($binary, 0, strlen(Onion::MAGIC))) { $addr = strtolower(Base32::encode($buffer->slice(strlen(Onion::MAGIC))->getBinary())) . '.onion'; $ip = new Onion($addr); } elseif (Ipv4::MAGIC === substr($binary, 0, strlen(Ipv4::MAGIC))) { $end = $buffer->slice(strlen(Ipv4::MAGIC), 4); $ip = new Ipv4(long2ip($end->getInt())); } else { $addr = []; foreach (str_split($binary, 2) as $segment) { $addr[] = bin2hex($segment); } $addr = implode(":", $addr); $ip = new Ipv6($addr); } return $ip; }
/** * 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; }
/** * @expectedException \Exception */ public function testReadBytesBeyondLength() { $bytes = '41424344'; $parser = new Parser($bytes); $parser->readBytes(5); }
/** * @param Parser $parser * @return PrivateKey * @throws \BitWasp\Buffertools\Exceptions\ParserOutOfRange */ public function fromParser(Parser $parser) { $compressed = $this->haveNextCompressed; $this->haveNextCompressed = false; return $this->ecAdapter->getPrivateKey($parser->readBytes(32)->getInt(), $compressed); }
/** * Take an array containing serializable objects. * @param SerializableInterface []|Buffer[] * @return $this */ public function writeArray($serializable) { $parser = new Parser(Buffertools::numToVarInt(count($serializable)), $this->math); foreach ($serializable as $object) { if ($object instanceof SerializableInterface) { $object = $object->getBuffer(); } if ($object instanceof Buffer) { $parser->writeBytes($object->getSize(), $object); } else { throw new \RuntimeException('Input to writeArray must be Buffer[], or SerializableInterface[]'); } } $this->string .= $parser->getBuffer()->getBinary(); return $this; }
<?php require "../vendor/autoload.php"; use BitWasp\Buffertools\Buffer; use BitWasp\Buffertools\Parser; // Parsers read Buffers $buffer = new Buffer('abc'); $parser = new Parser($buffer); // Call readBytes to unpack the data /** @var Buffer[] $set */ $set = [$parser->readBytes(1), $parser->readBytes(1), $parser->readBytes(1)]; foreach ($set as $item) { echo $item->getBinary() . PHP_EOL; }
/** * 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) { $parser = new Parser(); $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"); } $parser->writeBytes(1, '00')->writeBytes(32, $this->getPrivateKey()->getBuffer()); } else { $parser->writeBytes(33, $this->getPublicKey()->getBuffer()); } return $parser->writeInt(4, $sequence)->getBuffer(); }
/** * {@inheritdoc} * @see \BitWasp\Bitcoin\Block\BlockHeaderInterface::getBlockHash() */ public function getBlockHash() { $parser = new Parser(); return $parser->writeBytes(32, Hash::sha256d($this->getBuffer()), true)->getBuffer()->getHex(); }
/** * 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 $inputToSign * @param int $sighashType * @return Buffer * @throws \Exception */ public function calculate(ScriptInterface $txOutScript, $inputToSign, $sighashType = SignatureHashInterface::SIGHASH_ALL) { $copy = $this->transaction->makeCopy(); $inputs = $copy->getInputs(); $outputs = $copy->getOutputs(); if ($inputToSign > count($inputs)) { throw new \Exception('Input does not exist'); } // Default SIGHASH_ALL procedure: null all input scripts $inputCount = count($inputs); for ($i = 0; $i < $inputCount; $i++) { $inputs->getInput($i)->setScript(new Script()); } $inputs->getInput($inputToSign)->setScript($txOutScript); $math = Bitcoin::getMath(); if ($math->bitwiseAnd($sighashType, 31) == SignatureHashInterface::SIGHASH_NONE) { // Set outputs to empty vector, and set sequence number of inputs to 0. $copy->setOutputs(new TransactionOutputCollection()); // Let the others update at will. Set sequence of inputs we're not signing to 0. $inputCount = count($inputs); for ($i = 0; $i < $inputCount; $i++) { if ($math->cmp($i, $inputToSign) !== 0) { $inputs->getInput($i)->setSequence(0); } } } elseif ($math->bitwiseAnd($sighashType, 31) == SignatureHashInterface::SIGHASH_SINGLE) { // Resize output array to $inputToSign + 1, set remaining scripts to null, // and set sequence's to zero. $nOutput = $inputToSign; if ($math->cmp($nOutput, count($outputs)) >= 0) { return Buffer::hex('0100000000000000000000000000000000000000000000000000000000000000'); } // Resize.. $outputs = $outputs->slice(0, $nOutput + 1)->getOutputs(); // Set to null for ($i = 0; $i < $nOutput; $i++) { $outputs[$i] = new TransactionOutput($math->getBinaryMath()->getTwosComplement(-1, 64), new Script()); } $copy->setOutputs(new TransactionOutputCollection($outputs)); // Let the others update at will. Set sequence of inputs we're not signing to 0. $inputCount = count($inputs); for ($i = 0; $i < $inputCount; $i++) { if ($math->cmp($i, $inputToSign) != 0) { $inputs->getInput($i)->setSequence(0); } } } // This can happen regardless of whether it's ALL, NONE, or SINGLE if ($math->bitwiseAnd($sighashType, SignatureHashInterface::SIGHASH_ANYONECANPAY)) { $input = $inputs->getInput($inputToSign); $copy->setInputs(new TransactionInputCollection([$input])); } // Serialize the TxCopy and append the 4 byte hashtype (little endian); $txParser = new Parser($copy->getBuffer()); $txParser->writeInt(4, $sighashType, true); return Hash::sha256d($txParser->getBuffer()); }