コード例 #1
0
ファイル: OutPoint.php プロジェクト: nmarley/bitcoin-php
 /**
  * OutPoint constructor.
  * @param BufferInterface $hashPrevOutput
  * @param int $nPrevOutput
  */
 public function __construct(BufferInterface $hashPrevOutput, $nPrevOutput)
 {
     if ($hashPrevOutput->getSize() !== 32) {
         throw new \InvalidArgumentException('OutPoint: hashPrevOut must be a 32-byte Buffer');
     }
     $this->hashPrevOutput = $hashPrevOutput;
     $this->nPrevOutput = $nPrevOutput;
     $this->initFunctionAlias('txid', 'getTxId')->initFunctionAlias('vout', 'getVout');
 }
コード例 #2
0
ファイル: BlockIndex.php プロジェクト: Bit-Wasp/node-php
 /**
  * @param BlockIndexInterface $index
  * @return bool
  */
 public function isNext(BlockIndexInterface $index)
 {
     if (false === $this->hash->equals($index->getHeader()->getPrevBlock())) {
         return false;
     }
     if (false === ($index->getHeight() == $this->height + 1)) {
         return false;
     }
     return true;
 }
コード例 #3
0
 /**
  * @param int $type
  * @param BufferInterface $hash
  */
 public function __construct($type, BufferInterface $hash)
 {
     if (false === $this->checkType($type)) {
         throw new \InvalidArgumentException('Invalid type in InventoryVector');
     }
     if (false === (32 === $hash->getSize())) {
         throw new \InvalidArgumentException('Hash size must be 32 bytes');
     }
     $this->type = $type;
     $this->hash = $hash;
 }
コード例 #4
0
 /**
  * WitnessAddress constructor.
  * @param int $witnessVersion
  * @param BufferInterface $hash
  */
 public function __construct($witnessVersion, BufferInterface $hash)
 {
     if (!is_int($witnessVersion)) {
         throw new \RuntimeException('Witness version must be an integer');
     }
     if ($hash->getSize() !== 32) {
         throw new \RuntimeException('Hash for P2WSH address must be 32 bytes');
     }
     $this->witnessVersion = $witnessVersion;
     $this->hash = $hash->getHex();
 }
コード例 #5
0
ファイル: ProofOfWork.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $hash
  * @param int|string $nBits
  * @return bool
  */
 public function check(BufferInterface $hash, $nBits)
 {
     $negative = false;
     $overflow = false;
     $target = $this->math->writeCompact($nBits, $negative, $overflow);
     if ($negative || $overflow || $this->math->cmp($target, 0) === 0 || $this->math->cmp($target, $this->getMaxTarget()) > 0) {
         throw new \RuntimeException('nBits below minimum work');
     }
     if ($this->math->cmp($hash->getInt(), $target) > 0) {
         throw new \RuntimeException("Hash doesn't match nBits");
     }
     return true;
 }
コード例 #6
0
 /**
  * Generate a master private key given a
  * @param BufferInterface $seed
  * @param EcAdapterInterface $ecAdapter
  * @return ElectrumKey
  */
 public static function generateMasterKey(BufferInterface $seed, EcAdapterInterface $ecAdapter = null)
 {
     // Really weird, did electrum actually hash hex string seeds?
     $binary = $oldseed = $seed->getHex();
     // Perform sha256 hash 5 times per iteration
     for ($i = 0; $i < 5 * 20000; $i++) {
         // Hash should return binary data
         $binary = hash('sha256', $binary . $oldseed, true);
     }
     $ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
     // Convert binary data to hex.
     $str = new Buffer($binary, 32, $ecAdapter->getMath());
     return self::fromSecretExponent($str->getInt(), $ecAdapter);
 }
コード例 #7
0
ファイル: Bip39Mnemonic.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $entropy
  * @return array
  */
 public function entropyToWords(BufferInterface $entropy)
 {
     $math = $this->ecAdapter->getMath();
     $ENT = $entropy->getSize() * 8;
     $CS = $ENT / 32;
     $entBits = $math->baseConvert($entropy->getHex(), 16, 2);
     $csBits = $this->calculateChecksum($entropy, $CS);
     $bits = str_pad($entBits . $csBits, $ENT + $CS, '0', STR_PAD_LEFT);
     $result = [];
     foreach (str_split($bits, 11) as $bit) {
         $idx = $math->baseConvert($bit, 2, 10);
         $result[] = $this->wordList->getWord($idx);
     }
     return $result;
 }
コード例 #8
0
ファイル: BlockHeader.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param int|string $version
  * @param BufferInterface $prevBlock
  * @param BufferInterface $merkleRoot
  * @param int|string $timestamp
  * @param BufferInterface $bits
  * @param int|string $nonce
  */
 public function __construct($version, BufferInterface $prevBlock, BufferInterface $merkleRoot, $timestamp, BufferInterface $bits, $nonce)
 {
     if ($prevBlock->getSize() !== 32) {
         throw new \InvalidArgumentException('Block header prevBlock must be a 32-byte Buffer');
     }
     if ($merkleRoot->getSize() !== 32) {
         throw new \InvalidArgumentException('Block header prevBlock must be a 32-byte Buffer');
     }
     $this->version = $version;
     $this->prevBlock = $prevBlock;
     $this->merkleRoot = $merkleRoot;
     $this->timestamp = $timestamp;
     $this->bits = $bits;
     $this->nonce = $nonce;
     $this->initFunctionAlias('version', 'getVersion')->initFunctionAlias('prevBlock', 'getPrevBlock')->initFunctionAlias('merkleRoot', 'getMerkleRoot')->initFunctionAlias('timestamp', 'getTimestamp')->initFunctionAlias('bits', 'getBits')->initFunctionAlias('nonce', 'getNonce');
 }
コード例 #9
0
 /**
  * @param BufferInterface $sig
  * @return bool
  * @throws SignatureNotCanonical
  */
 public static function isDERSignature(BufferInterface $sig)
 {
     $checkVal = function ($fieldName, $start, $length, $binaryString) {
         if ($length === 0) {
             throw new SignatureNotCanonical('Signature ' . $fieldName . ' length is zero');
         }
         $typePrefix = ord(substr($binaryString, $start - 2, 1));
         if ($typePrefix !== 0x2) {
             throw new SignatureNotCanonical('Signature ' . $fieldName . ' value type mismatch');
         }
         $val = substr($binaryString, $start, $length);
         $vAnd = $val[0] & chr(0x80);
         if (ord($vAnd) === 128) {
             throw new SignatureNotCanonical('Signature ' . $fieldName . ' value is negative');
         }
         if ($length > 1 && $val[0] === "" && !ord($val[1] & chr(0x80))) {
             throw new SignatureNotCanonical('Signature ' . $fieldName . ' value excessively padded');
         }
     };
     $bin = $sig->getBinary();
     $size = $sig->getSize();
     if ($size < 9) {
         throw new SignatureNotCanonical('Signature too short');
     }
     if ($size > 73) {
         throw new SignatureNotCanonical('Signature too long');
     }
     if (ord($bin[0]) !== 0x30) {
         throw new SignatureNotCanonical('Signature has wrong type');
     }
     if (ord($bin[1]) !== $size - 3) {
         throw new SignatureNotCanonical('Signature has wrong length marker');
     }
     $lenR = ord($bin[3]);
     $startR = 4;
     if (5 + $lenR >= $size) {
         throw new SignatureNotCanonical('Signature S length misplaced');
     }
     $lenS = ord($bin[5 + $lenR]);
     $startS = 4 + $lenR + 2;
     if ($lenR + $lenS + 7 !== $size) {
         throw new SignatureNotCanonical('Signature R+S length mismatch');
     }
     $checkVal('R', $startR, $lenR, $bin);
     $checkVal('S', $startS, $lenS, $bin);
     return true;
 }
コード例 #10
0
 /**
  * @param BufferInterface $entropy
  * @return array
  * @throws \Exception
  */
 public function entropyToWords(BufferInterface $entropy)
 {
     $math = $this->ecAdapter->getMath();
     $n = count($this->wordList);
     $wordArray = [];
     $chunks = $entropy->getSize() / 4;
     for ($i = 0; $i < $chunks; $i++) {
         $x = $entropy->slice(4 * $i, 4)->getInt();
         $index1 = $math->mod($x, $n);
         $index2 = $math->mod($math->add($math->div($x, $n), $index1), $n);
         $index3 = $math->mod($math->add($math->div($math->div($x, $n), $n), $index2), $n);
         $wordArray[] = $this->wordList->getWord($index1);
         $wordArray[] = $this->wordList->getWord($index2);
         $wordArray[] = $this->wordList->getWord($index3);
     }
     return $wordArray;
 }
コード例 #11
0
ファイル: PublicKey.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $publicKey
  * @return bool
  */
 public static function isCompressedOrUncompressed(BufferInterface $publicKey)
 {
     $vchPubKey = $publicKey->getBinary();
     if ($publicKey->getSize() < 33) {
         return false;
     }
     if (ord($vchPubKey[0]) === 0x4) {
         if ($publicKey->getSize() !== 65) {
             // Invalid length for uncompressed key
             return false;
         }
     } elseif (in_array($vchPubKey[0], array(hex2bin(self::KEY_COMPRESSED_EVEN), hex2bin(self::KEY_COMPRESSED_ODD)))) {
         if ($publicKey->getSize() !== 33) {
             return false;
         }
     } else {
         return false;
     }
     return true;
 }
コード例 #12
0
ファイル: Base58.php プロジェクト: nmarley/bitcoin-php
 /**
  * Encode a given hex string in base58
  *
  * @param BufferInterface $binary
  * @return string
  * @throws \Exception
  */
 public static function encode(BufferInterface $binary)
 {
     $size = $binary->getSize();
     if ($binary->getBinary() === '') {
         return '';
     }
     $math = Bitcoin::getMath();
     $orig = $binary->getBinary();
     $decimal = $binary->getInt();
     $return = '';
     while ($math->cmp($decimal, 0) > 0) {
         list($decimal, $rem) = $math->divQr($decimal, 58);
         $return .= self::$base58chars[$rem];
     }
     $return = strrev($return);
     //leading zeros
     for ($i = 0; $i < $size && $orig[$i] === ""; $i++) {
         $return = '1' . $return;
     }
     return $return;
 }
コード例 #13
0
ファイル: Number.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $buffer
  * @return int
  */
 private function parseBuffer(BufferInterface $buffer)
 {
     $size = $buffer->getSize();
     if ($size === 0) {
         return '0';
     }
     $chars = array_map(function ($binary) {
         return ord($binary);
     }, str_split($buffer->getBinary(), 1));
     $result = 0;
     for ($i = 0; $i < $size; $i++) {
         $mul = $this->math->mul($i, 8);
         $byte = $this->math->leftShift($chars[$i], $mul);
         $result = $this->math->bitwiseOr($result, $byte);
     }
     if ($chars[count($chars) - 1] & 0x80) {
         $mask = gmp_strval(gmp_com($this->math->leftShift(0x80, 8 * ($size - 1))), 10);
         return $this->math->sub(0, $this->math->bitwiseAnd($result, $mask));
     }
     return $result;
 }
コード例 #14
0
ファイル: ScriptCreator.php プロジェクト: nmarley/bitcoin-php
 /**
  * Push data into the stack.
  *
  * @param $data
  * @return $this
  * @throws \Exception
  */
 public function push(BufferInterface $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;
 }
コード例 #15
0
ファイル: BlockRequest.php プロジェクト: Bit-Wasp/node-php
 /**
  * @param BufferInterface $hash
  * @return $this
  */
 public function markReceived(BufferInterface $hash)
 {
     unset($this->inFlight[$hash->getBinary()]);
     return $this;
 }
コード例 #16
0
ファイル: ChainContainer.php プロジェクト: Bit-Wasp/node-php
 /**
  * @param BufferInterface $hash
  * @return bool|ChainView
  */
 public function isTip(BufferInterface $hash)
 {
     foreach ($this->segments as $segment) {
         if ($hash->equals($segment->getLast()->getHash())) {
             return $this->view($segment);
         }
     }
     return false;
 }
コード例 #17
0
ファイル: Db.php プロジェクト: Bit-Wasp/node-php
 /**
  * @param BufferInterface $hash
  * @param int $numAncestors
  * @return array
  */
 public function findSuperMajorityInfoByHash(BufferInterface $hash, $numAncestors = 1000)
 {
     $this->fetchLftRgtByHash->execute(['hash' => $hash->getBinary()]);
     $id = $this->fetchLftRgtByHash->fetch(\PDO::FETCH_ASSOC);
     $this->fetchSuperMajorityVersions->execute(['lft' => $id['lft'], 'rgt' => $id['rgt']]);
     $stream = $this->fetchSuperMajorityVersions->fetchAll(\PDO::FETCH_COLUMN);
     return $stream;
 }
コード例 #18
0
 /**
  * @param PublicKeyInterface $publicKey
  * @return bool
  */
 public function checkInvolvesKey(PublicKeyInterface $publicKey)
 {
     return $publicKey->getPubKeyHash()->getBinary() === $this->hash->getBinary();
 }
コード例 #19
0
ファイル: Script.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $script
  * @param Opcodes|null $opCodes
  */
 public function __construct(BufferInterface $script = null, Opcodes $opCodes = null)
 {
     $this->script = $script instanceof BufferInterface ? $script->getBinary() : '';
     $this->opCodes = $opCodes ?: new Opcodes();
 }
コード例 #20
0
ファイル: EcAdapter.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $publicKey
  * @return PublicKeyInterface
  * @throws \Exception
  */
 public function publicKeyFromBuffer(BufferInterface $publicKey)
 {
     $compressed = $publicKey->getSize() == PublicKey::LENGTH_COMPRESSED;
     $xCoord = $publicKey->slice(1, 32)->getInt();
     return new PublicKey($this, $this->getGenerator()->getCurve()->getPoint($xCoord, $compressed ? $this->recoverYfromX($xCoord, $publicKey->slice(0, 1)->getHex()) : $publicKey->slice(33, 32)->getInt()), $compressed);
 }
コード例 #21
0
ファイル: EcAdapter.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $msg32
  * @param PrivateKey $privateKey
  * @return CompactSignature
  */
 private function doSignCompact(BufferInterface $msg32, PrivateKey $privateKey)
 {
     $sig_t = '';
     /** @var resource $sig_t */
     if (1 !== secp256k1_ecdsa_sign_recoverable($this->context, $msg32->getBinary(), $privateKey->getBinary(), $sig_t)) {
         throw new \RuntimeException('Secp256k1: failed to sign');
     }
     $recid = '';
     $ser = '';
     if (!secp256k1_ecdsa_recoverable_signature_serialize_compact($this->context, $sig_t, $ser, $recid)) {
         throw new \RuntimeException('Failed to obtain recid');
     }
     unset($ser);
     return new CompactSignature($this, $sig_t, $recid, $privateKey->isCompressed());
 }
コード例 #22
0
ファイル: Hash.php プロジェクト: nmarley/bitcoin-php
 /**
  * Do HMAC hashing on $data and $salt
  *
  * @param string $algo
  * @param BufferInterface $data
  * @param BufferInterface $salt
  * @return BufferInterface
  */
 public static function hmac($algo, BufferInterface $data, BufferInterface $salt)
 {
     return new Buffer(hash_hmac($algo, $data->getBinary(), $salt->getBinary(), true));
 }
コード例 #23
0
ファイル: ChainView.php プロジェクト: Bit-Wasp/node-php
 /**
  * @param BufferInterface $buffer
  * @return int
  */
 public function getHeightFromHash(BufferInterface $buffer)
 {
     $binary = $buffer->getBinary();
     foreach ($this->segments as $segment) {
         $hashes = $this->container->getHashes($segment);
         if (isset($hashes[$binary])) {
             return $hashes[$binary];
         }
     }
     throw new \RuntimeException('Hash not found');
 }
コード例 #24
0
ファイル: Address.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $hash
  */
 public function __construct(BufferInterface $hash)
 {
     $this->hash = $hash->getHex();
 }
コード例 #25
0
ファイル: Checker.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param BufferInterface $signature
  * @param int $flags
  * @return $this
  * @throws \BitWasp\Bitcoin\Exceptions\ScriptRuntimeException
  */
 public function checkSignatureEncoding(BufferInterface $signature, $flags)
 {
     if ($signature->getSize() === 0) {
         return $this;
     }
     if (($flags & (Interpreter::VERIFY_DERSIG | Interpreter::VERIFY_LOW_S | Interpreter::VERIFY_STRICTENC)) != 0 && !$this->isValidSignatureEncoding($signature)) {
         throw new ScriptRuntimeException(Interpreter::VERIFY_DERSIG, 'Signature with incorrect encoding');
     } else {
         if (($flags & Interpreter::VERIFY_LOW_S) != 0 && !$this->isLowDerSignature($signature)) {
             throw new ScriptRuntimeException(Interpreter::VERIFY_LOW_S, 'Signature s element was not low');
         } else {
             if (($flags & Interpreter::VERIFY_STRICTENC) != 0 && !$this->isDefinedHashtypeSignature($signature)) {
                 throw new ScriptRuntimeException(Interpreter::VERIFY_STRICTENC, 'Signature with invalid hashtype');
             }
         }
     }
     return $this;
 }
コード例 #26
0
ファイル: Interpreter.php プロジェクト: nmarley/bitcoin-php
 /**
  * @param int $opCode
  * @param BufferInterface $pushData
  * @return bool
  * @throws \Exception
  */
 public function checkMinimalPush($opCode, BufferInterface $pushData)
 {
     $pushSize = $pushData->getSize();
     $binary = $pushData->getBinary();
     if ($pushSize === 0) {
         return $opCode === Opcodes::OP_0;
     } elseif ($pushSize === 1) {
         $first = ord($binary[0]);
         if ($first >= 1 && $first <= 16) {
             return $opCode === Opcodes::OP_1 + ($first - 1);
         } elseif ($first === 0x81) {
             return $opCode === Opcodes::OP_1NEGATE;
         }
     } elseif ($pushSize <= 75) {
         return $opCode === $pushSize;
     } elseif ($pushSize <= 255) {
         return $opCode === Opcodes::OP_PUSHDATA1;
     } elseif ($pushSize <= 65535) {
         return $opCode === Opcodes::OP_PUSHDATA2;
     }
     return true;
 }