Skip to content

Commit ede21ba

Browse files
committed
alt p2pkh script
1 parent b28df8b commit ede21ba

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

src/ScriptPubKey.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ public function isPayToPubKeyHash(): bool
6666
ord($this->data[-1]) == Opcodes::OP_CHECKSIG;
6767
}
6868

69+
/**
70+
* handle output of TX 059787f0673ab2c00b8f2f9810fdd14b0cd6a3034cc44dc30de124f606d3670a
71+
* @return bool
72+
*/
73+
public function isPayToPubKeyHashAlt(): bool
74+
{
75+
return $this->size == 26 &&
76+
ord($this->data[0]) == Opcodes::OP_DUP &&
77+
ord($this->data[1]) == Opcodes::OP_HASH160 &&
78+
ord($this->data[2]) == Opcodes::OP_PUSHDATA1 &&
79+
ord($this->data[3]) == 20 &&
80+
ord($this->data[-2]) == Opcodes::OP_EQUALVERIFY &&
81+
ord($this->data[-1]) == Opcodes::OP_CHECKSIG;
82+
}
83+
6984
/**
7085
* @return bool
7186
*/
@@ -149,6 +164,10 @@ public function getOutputAddress(Bitcoin $network = null): string
149164
return $addressSerializer->getPayToPubKeyHash(substr($this->data, 3, 20));
150165
}
151166

167+
if ($this->isPayToPubKeyHashAlt()) {
168+
return $addressSerializer->getPayToPubKeyHash(substr($this->data, 4, 20));
169+
}
170+
152171
if ($this->isPayToScriptHash()) {
153172
return $addressSerializer->getPayToScriptHash(substr($this->data, 2, 20));
154173
}

src/UnspentOutput.php

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
*/
1515
class UnspentOutput
1616
{
17+
const SPECIAL_SCRIPTS = 6;
18+
1719
/**
1820
* @var string
1921
*/
@@ -112,30 +114,35 @@ public function getAddress(Bitcoin $network = null): string
112114

113115
// try do decompress script first
114116
switch ($this->type) {
115-
case 0x00:
117+
case 0:
116118
return $addressSerializer->getPayToPubKeyHash($this->script);
117119

118-
case 0x01:
120+
case 1:
119121
return $addressSerializer->getPayToScriptHash($this->script);
120122

121-
case 0x02:
122-
case 0x03:
123+
case 2:
124+
case 3:
123125
$pubKey = chr($this->type) . $this->script;
124126
return $addressSerializer->getPayToPubKey($pubKey);
125127

126-
case 0x04:
127-
case 0x05:
128+
case 4:
129+
case 5:
128130
$pubKey = chr($this->type - 2) . $this->script;
129131
$decompressed = PublicKey::parse($pubKey)->decompress()->serialize();
130132
return $addressSerializer->getPayToPubKey($decompressed);
131133

132-
case 0x1c;
134+
case 22 + static::SPECIAL_SCRIPTS;
133135
$addressSerializer->getPayToWitnessPubKeyHash($this->script);
134136
break;
135137

136-
case 0x28:
138+
case 34 + static::SPECIAL_SCRIPTS:
137139
$addressSerializer->getPayToWitnessScriptHash($this->script);
138140
break;
141+
142+
// invalid public key prefix
143+
case 35 + static::SPECIAL_SCRIPTS:
144+
case 67 + static::SPECIAL_SCRIPTS:
145+
throw new ScriptException('Unable to decode output address.');
139146
}
140147

141148
// fallback

tests/ScriptPubKeyTest.php

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function testReturn()
2222
// [pubkey] OP_CHECKSIG
2323
public function testParseP2PK()
2424
{
25-
$hex = '41'; // OP_PUSHDATA
25+
$hex = '41'; // 65
2626
$hex .= '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'; // pubkey
2727
$hex .= 'ac'; // OP_CHECKSIG
2828

@@ -35,7 +35,7 @@ public function testParseP2PK()
3535
// [pubkey] OP_CHECKSIG
3636
public function testParseP2PKCompressed()
3737
{
38-
$hex = '21'; // OP_PUSHDATA
38+
$hex = '21'; // 33
3939
$hex .= '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'; // pubkey
4040
$hex .= 'ac'; // OP_CHECKSIG
4141

@@ -50,7 +50,7 @@ public function testParseP2PKH()
5050
{
5151
$hex = '76'; // OP_DUP
5252
$hex .= 'a9'; // OP_HASH160
53-
$hex .= '14'; // OP_PUSHDATA
53+
$hex .= '14'; // 20
5454
$hex .= '91b24bf9f5288532960ac687abb035127b1d28a5'; // pubkey hash
5555
$hex .= '88'; // OP_EQUALVERIFY
5656
$hex .= 'ac'; // OP_CHECKSIG
@@ -61,11 +61,26 @@ public function testParseP2PKH()
6161
$this->assertEquals($script->getOutputAddress(), '1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm');
6262
}
6363

64+
public function testParseP2PKHAlt()
65+
{
66+
$hex = '76'; // OP_DUP
67+
$hex .= 'a9'; // OP_HASH160
68+
$hex .= '4c'; // OP_PUSHDATA1
69+
$hex .= '14'; // 20
70+
$hex .= 'cd4967766b612eb44345fb00f316d890cd3d508688'; // pubkey hash
71+
$hex .= 'ac'; // OP_CHECKSIG
72+
73+
$script = new ScriptPubKey(hex2bin($hex));
74+
75+
$this->assertTrue($script->isPayToPubKeyHashAlt());
76+
$this->assertEquals($script->getOutputAddress(), '1KiTTY2sRjPRdobHdNTzBVv7rBiNG1tX2E');
77+
}
78+
6479
// OP_HASH160 [hash] OP_EQUAL
6580
public function testParseP2SH()
6681
{
6782
$hex = 'a9'; // OP_HASH160
68-
$hex .= '14'; // OP_PUSHDATA
83+
$hex .= '14'; // 20
6984
$hex .= '91b24bf9f5288532960ac687abb035127b1d28a5'; // script hash
7085
$hex .= '87'; // OP_EQUAL
7186

@@ -78,14 +93,14 @@ public function testParseP2SH()
7893
// [numsigs] [...pubkeys...] [numpubkeys] OP_CHECKMULTISIG
7994
public function testParseMultisig()
8095
{
81-
$hex = '53'; // OP_3
82-
$hex .= '14'; // OP_PUSHDATA
96+
$hex = '53'; // 3
97+
$hex .= '14'; // 20
8398
$hex .= '91b24bf9f5288532960ac687abb035127b1d28a5'; // pubkey hash
84-
$hex .= '14'; // OP_PUSHDATA
99+
$hex .= '14'; // 20
85100
$hex .= 'd6c8e828c1eca1bba065e1b83e1dc2a36e387a42'; // pubkey hash
86-
$hex .= '14'; // OP_PUSHDATA
101+
$hex .= '14'; // 20
87102
$hex .= 'ec7eced2c57ed1292bc4eb9bfd13c9f7603bc338'; // pubkey hash
88-
$hex .= '52'; // OP_2
103+
$hex .= '52'; // 2
89104
$hex .= 'ae'; // OP_CHECKMULTISIG
90105

91106
$script = new ScriptPubKey(hex2bin($hex));
@@ -97,7 +112,7 @@ public function testParseMultisig()
97112
public function testParseP2WPKH()
98113
{
99114
$hex = '00'; // segwit version
100-
$hex .= '14'; // OP_PUSHDATA
115+
$hex .= '14'; // 20
101116
$hex .= '536523b38a207338740797cd03c3312e81408d53'; // pubkey hash
102117

103118
$script = new ScriptPubKey(hex2bin($hex));
@@ -110,7 +125,7 @@ public function testParseP2WPKH()
110125
public function testParseP2WSH()
111126
{
112127
$hex = '00'; // segwit version
113-
$hex .= '20'; // OP_PUSHDATA
128+
$hex .= '20'; // 20
114129
$hex .= '701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d'; // hash
115130

116131
$script = new ScriptPubKey(hex2bin($hex));

0 commit comments

Comments
 (0)