/** * @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(); }
/** * @return bool */ public function isMultisig() { if (count($this->decoded) < 3) { return false; } $final = end($this->decoded); if (!$final || !$final->isPush()) { return false; } $script = new Script($final->getData()); $decoded = $script->getScriptParser()->decode(); $count = count($decoded); $mOp = $decoded[0]; $nOp = $decoded[$count - 2]; if ($mOp->isPush() || $nOp->isPush()) { return false; } if ($mOp->getOp() < Opcodes::OP_0 || $nOp->getOp() > Opcodes::OP_16) { return false; } /** @var Operation[] $keys */ $keys = array_slice($decoded, 1, -2); $keysValid = true; foreach ($keys as $key) { $keysValid &= $key->isPush() && PublicKey::isCompressedOrUncompressed($key->getData()); } return $keysValid; }
/** * @param BufferInterface $publicKey * @param int $flags * @return $this * @throws \Exception */ public function checkPublicKeyEncoding(BufferInterface $publicKey, $flags) { if (($flags & Interpreter::VERIFY_STRICTENC) != 0 && !PublicKey::isCompressedOrUncompressed($publicKey)) { throw new ScriptRuntimeException(Interpreter::VERIFY_STRICTENC, 'Public key with incorrect encoding'); } return $this; }
/** * Attempt to calculate the public key recovery param by trial and error * * @param int|string $r * @param int|string $s * @param Buffer $messageHash * @param PublicKey $publicKey * @return int * @throws \Exception */ public function calcPubKeyRecoveryParam($r, $s, Buffer $messageHash, PublicKey $publicKey) { $Q = $publicKey->getPoint(); for ($i = 0; $i < 4; $i++) { try { $recover = $this->recover($messageHash, new CompactSignature($this, $r, $s, $i, $publicKey->isCompressed())); if ($recover->getPoint()->equals($Q)) { return $i; } } catch (\Exception $e) { continue; } } throw new \Exception('Failed to find valid recovery factor'); }
/** * @param Buffer $publicKey * @return $this * @throws \Exception */ public function checkPublicKeyEncoding(Buffer $publicKey) { if ($this->flags->checkFlags(self::VERIFY_STRICTENC) && !PublicKey::isCompressedOrUncompressed($publicKey)) { throw new ScriptRuntimeException(self::VERIFY_STRICTENC, 'Public key with incorrect encoding'); } return $this; }
/** * @return bool */ public function isMultisig() { $count = count($this->decoded); if ($count <= 3) { return false; } $mOp = $this->decoded[0]; $nOp = $this->decoded[$count - 2]; $checksig = $this->decoded[$count - 1]; if ($mOp->isPush() || $nOp->isPush() || $checksig->isPush()) { return false; } /** @var Operation[] $vKeys */ $vKeys = array_slice($this->decoded, 1, -2); foreach ($vKeys as $key) { if (!$key->isPush() || !PublicKey::isCompressedOrUncompressed($key->getData())) { return false; } } return $mOp->getOp() >= Opcodes::OP_0 && $nOp->getOp() <= Opcodes::OP_16 && $checksig->getOp() === Opcodes::OP_CHECKMULTISIG; }