Skip to content

Commit b28df8b

Browse files
committed
fast output decompress
1 parent d4604c0 commit b28df8b

File tree

2 files changed

+33
-27
lines changed

2 files changed

+33
-27
lines changed

src/ScriptPubKey.php

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,32 @@ public function isReturn(): bool
2121
return $this->size >= 1 && ord($this->data[0]) == Opcodes::OP_RETURN;
2222
}
2323

24+
/**
25+
* @return bool
26+
*/
27+
public function isEmpty(): bool
28+
{
29+
return $this->size == 0;
30+
}
31+
2432
/**
2533
* @return bool
2634
*/
2735
public function isPayToPubKey(): bool
2836
{
2937
// compressed pubkey
30-
if ($this->size == 35 &&
31-
ord($this->data[0]) == 33 &&
32-
ord($this->data[-1]) == Opcodes::OP_CHECKSIG &&
33-
($this->data[1] == "\x02" || $this->data[1] == "\x03")) {
38+
if ($this->size == PublicKey::LENGTH_COMPRESSED + 2 &&
39+
ord($this->data[0]) == PublicKey::LENGTH_COMPRESSED &&
40+
($this->data[1] == PublicKey::PREFIX_COMPRESSED_EVEN || $this->data[1] == PublicKey::PREFIX_COMPRESSED_ODD) &&
41+
ord($this->data[-1]) == Opcodes::OP_CHECKSIG) {
3442
return true;
3543
}
3644

3745
// uncompressed pubkey
38-
if ($this->size == 67 &&
39-
ord($this->data[0]) == 65 &&
40-
ord($this->data[-1]) == Opcodes::OP_CHECKSIG &&
41-
$this->data[1] == "\x04") {
46+
if ($this->size == PublicKey::LENGTH_UNCOMPRESSED + 2 &&
47+
ord($this->data[0]) == PublicKey::LENGTH_UNCOMPRESSED &&
48+
$this->data[1] == PublicKey::PREFIX_UNCOMPRESSED &&
49+
ord($this->data[-1]) == Opcodes::OP_CHECKSIG) {
4250
return true;
4351
}
4452

@@ -127,40 +135,30 @@ public function isPayToWitnessScriptHash(): bool
127135
*/
128136
public function getOutputAddress(Bitcoin $network = null): string
129137
{
130-
try {
131-
$operations = $this->parse();
132-
} catch (\Exception $exception) {
133-
throw new ScriptException('Unable to decode output address (script parse error).');
134-
}
135-
136138
$addressSerializer = new AddressSerializer($network);
137139

138140
if ($this->isPayToPubKey()) {
139-
return $addressSerializer->getPayToPubKey($operations[0]->data);
141+
if ($this->size == 35) {
142+
return $addressSerializer->getPayToPubKey(substr($this->data, 1, 33));
143+
} elseif ($this->size == 67) {
144+
return $addressSerializer->getPayToPubKey(substr($this->data, 1, 65));
145+
}
140146
}
141147

142148
if ($this->isPayToPubKeyHash()) {
143-
return $addressSerializer->getPayToPubKeyHash($operations[2]->data);
149+
return $addressSerializer->getPayToPubKeyHash(substr($this->data, 3, 20));
144150
}
145151

146152
if ($this->isPayToScriptHash()) {
147-
return $addressSerializer->getPayToScriptHash($operations[1]->data);
153+
return $addressSerializer->getPayToScriptHash(substr($this->data, 2, 20));
148154
}
149155

150156
if ($this->isPayToWitnessPubKeyHash()) {
151-
return $addressSerializer->getPayToWitnessPubKeyHash($operations[1]->data);
157+
return $addressSerializer->getPayToWitnessPubKeyHash(substr($this->data, 2, 20));
152158
}
153159

154160
if ($this->isPayToWitnessScriptHash()) {
155-
return $addressSerializer->getPayToWitnessScriptHash($operations[1]->data);
156-
}
157-
158-
if ($this->isMultisig()) {
159-
throw new ScriptException('Unable to decode output address (multisig).');
160-
}
161-
162-
if ($this->isReturn()) {
163-
throw new ScriptException('Unable to decode output address (OP_RETURN).');
161+
return $addressSerializer->getPayToWitnessScriptHash(substr($this->data, 2, 32));
164162
}
165163

166164
throw new ScriptException('Unable to decode output address.');

src/UnspentOutput.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ public function getAddress(Bitcoin $network = null): string
128128
$pubKey = chr($this->type - 2) . $this->script;
129129
$decompressed = PublicKey::parse($pubKey)->decompress()->serialize();
130130
return $addressSerializer->getPayToPubKey($decompressed);
131+
132+
case 0x1c;
133+
$addressSerializer->getPayToWitnessPubKeyHash($this->script);
134+
break;
135+
136+
case 0x28:
137+
$addressSerializer->getPayToWitnessScriptHash($this->script);
138+
break;
131139
}
132140

133141
// fallback

0 commit comments

Comments
 (0)