Completed
Pull Request — master (#591)
by thomas
22:54 queued 09:12
created

CompactSignatureSerializer::doSerialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
crap 2.0185
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Serializer\Signature;
6
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Adapter\EcAdapter;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Signature\CompactSignature;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Signature\CompactSignatureSerializerInterface;
10
use BitWasp\Bitcoin\Crypto\EcAdapter\Signature\CompactSignatureInterface;
11
use BitWasp\Buffertools\Buffer;
12
use BitWasp\Buffertools\BufferInterface;
13
14
class CompactSignatureSerializer implements CompactSignatureSerializerInterface
15
{
16
    /**
17
     * @var EcAdapter
18
     */
19
    private $ecAdapter;
20
21
    /**
22
     * @param EcAdapter $ecAdapter
23
     */
24 11
    public function __construct(EcAdapter $ecAdapter)
25
    {
26 11
        $this->ecAdapter = $ecAdapter;
27 11
    }
28
29
    /**
30
     * @param CompactSignature $signature
31
     * @return BufferInterface
32
     */
33 5
    private function doSerialize(CompactSignature $signature)
34
    {
35 5
        $sig_t = '';
36 5
        $recid = '';
37 5
        if (!secp256k1_ecdsa_recoverable_signature_serialize_compact($this->ecAdapter->getContext(), $signature->getResource(), $sig_t, $recid)) {
38
            throw new \RuntimeException('Secp256k1 serialize compact failure');
39
        }
40
41 5
        return new Buffer(chr($signature->getFlags()) . $sig_t, 65);
42
    }
43
44
    /**
45
     * @param CompactSignatureInterface $signature
46
     * @return BufferInterface
47
     */
48 5
    public function serialize(CompactSignatureInterface $signature): BufferInterface
49
    {
50
        /** @var CompactSignature $signature */
51 5
        return $this->doSerialize($signature);
52
    }
53
54
    /**
55
     * @param BufferInterface $buffer
56
     * @return CompactSignatureInterface
57
     * @throws \Exception
58
     */
59 7
    public function parse(BufferInterface $buffer): CompactSignatureInterface
60
    {
61 7
        if ($buffer->getSize() !== 65) {
62 1
            throw new \RuntimeException('Compact Sig must be 65 bytes');
63
        }
64
65 6
        $byte = (int) $buffer->slice(0, 1)->getInt();
66 6
        $sig = $buffer->slice(1, 64);
67
68 6
        $recoveryFlags = $byte - 27;
69 6
        if ($recoveryFlags > 7) {
70
            throw new \RuntimeException('Invalid signature type');
71
        }
72
73 6
        $isCompressed = ($recoveryFlags & 4) !== 0;
74 6
        $recoveryId = $recoveryFlags - ($isCompressed ? 4 : 0);
75
76 6
        $sig_t = '';
77
        /** @var resource $sig_t */
78 6
        if (!secp256k1_ecdsa_recoverable_signature_parse_compact($this->ecAdapter->getContext(), $sig_t, $sig->getBinary(), $recoveryId)) {
79
            throw new \RuntimeException('Unable to parse compact signature');
80
        }
81
82 6
        return new CompactSignature($this->ecAdapter, $sig_t, $recoveryId, $isCompressed);
83
    }
84
}
85