-
Notifications
You must be signed in to change notification settings - Fork 1
/
addressv0.go
156 lines (139 loc) · 6.18 KB
/
addressv0.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (c) 2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package stdscript
import (
"github.com/EXCCoin/exccd/dcrec/secp256k1/v4"
"github.com/EXCCoin/exccd/txscript/v4/stdaddr"
)
// addrToSlice is a convenience function that returns a slice containing the
// passed address if the given error is nil and the address is NOT nil.
func addrToSlice(addr stdaddr.Address, err error) []stdaddr.Address {
if err != nil || addr == nil {
return nil
}
return []stdaddr.Address{addr}
}
// ExtractAddrsV0 analyzes the passed version 0 public key script and returns
// the associated script type along with any addresses associated with it when
// possible.
//
// This function only works for standard script types and any data that fails to
// produce a valid address is omitted from the results. This means callers must
// not blindly assume the slice will be of a particular length for a given
// returned script type and should always check the length prior to access in
// case the addresses were not able to be created.
func ExtractAddrsV0(pkScript []byte, params stdaddr.AddressParamsV0) (ScriptType, []stdaddr.Address) {
// Check for pay-to-pubkey-hash-ecdsa-secp256k1 script.
if h := ExtractPubKeyHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(h, params)
return STPubKeyHashEcdsaSecp256k1, addrToSlice(addr, err)
}
// Check for pay-to-script-hash.
if h := ExtractScriptHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressScriptHashV0FromHash(h, params)
return STScriptHash, addrToSlice(addr, err)
}
// Check for pay-to-pubkey-hash-ed25519 script.
if data := ExtractPubKeyHashEd25519V0(pkScript); data != nil {
addr, err := stdaddr.NewAddressPubKeyHashEd25519V0(data, params)
return STPubKeyHashEd25519, addrToSlice(addr, err)
}
// Check for pay-to-pubkey-hash-schnorr-secp256k1 script.
if data := ExtractPubKeyHashSchnorrSecp256k1V0(pkScript); data != nil {
addr, err := stdaddr.NewAddressPubKeyHashSchnorrSecp256k1V0(data, params)
return STPubKeyHashSchnorrSecp256k1, addrToSlice(addr, err)
}
// Check for pay-to-pubkey script.
if data := ExtractPubKeyV0(pkScript); data != nil {
// Note that this parse is done because the address is intentionally
// limited to compressed pubkeys, but consensus technically allows both
// compressed and uncompressed pubkeys for the underlying script.
var addrs []stdaddr.Address
pk, err := secp256k1.ParsePubKey(data)
if err == nil {
addr, err := stdaddr.NewAddressPubKeyEcdsaSecp256k1V0(pk, params)
addrs = addrToSlice(addr, err)
}
return STPubKeyEcdsaSecp256k1, addrs
}
// Check for pay-to-pubkey-ed25519 script.
if data := ExtractPubKeyEd25519V0(pkScript); data != nil {
addr, err := stdaddr.NewAddressPubKeyEd25519V0Raw(data, params)
return STPubKeyEd25519, addrToSlice(addr, err)
}
// Check for pay-to-pubkey-schnorr-secp256k1 script.
if data := ExtractPubKeySchnorrSecp256k1V0(pkScript); data != nil {
addr, err := stdaddr.NewAddressPubKeySchnorrSecp256k1V0Raw(data, params)
return STPubKeySchnorrSecp256k1, addrToSlice(addr, err)
}
// Check for multi-signature script.
details := ExtractMultiSigScriptDetailsV0(pkScript, true)
if details.Valid {
// Convert the public keys while skipping any that are invalid. Also,
// only allocate the slice of addresses if at least one valid address is
// found to avoid an unnecessary heap alloc that would otherwise happen
// when there are no valid addresses because the slice is returned.
var addrs []stdaddr.Address
for i := uint16(0); i < details.NumPubKeys; i++ {
pubkey, err := secp256k1.ParsePubKey(details.PubKeys[i])
if err == nil {
addr, err := stdaddr.NewAddressPubKeyEcdsaSecp256k1V0(pubkey, params)
if err == nil {
if addrs == nil {
addrs = make([]stdaddr.Address, 0, details.NumPubKeys-i)
}
addrs = append(addrs, addr)
}
}
}
return STMultiSig, addrs
}
// Check for stake submission script. Only stake-submission-tagged
// pay-to-pubkey-hash and pay-to-script-hash are allowed.
if h := ExtractStakeSubmissionPubKeyHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(h, params)
return STStakeSubmissionPubKeyHash, addrToSlice(addr, err)
}
if h := ExtractStakeSubmissionScriptHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressScriptHashV0FromHash(h, params)
return STStakeSubmissionScriptHash, addrToSlice(addr, err)
}
// Check for stake generation script. Only stake-generation-tagged
// pay-to-pubkey-hash and pay-to-script-hash are allowed.
if h := ExtractStakeGenPubKeyHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(h, params)
return STStakeGenPubKeyHash, addrToSlice(addr, err)
}
if h := ExtractStakeGenScriptHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressScriptHashV0FromHash(h, params)
return STStakeGenScriptHash, addrToSlice(addr, err)
}
// Check for stake revocation script. Only stake-revocation-tagged
// pay-to-pubkey-hash and pay-to-script-hash are allowed.
if h := ExtractStakeRevocationPubKeyHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(h, params)
return STStakeRevocationPubKeyHash, addrToSlice(addr, err)
}
if h := ExtractStakeRevocationScriptHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressScriptHashV0FromHash(h, params)
return STStakeRevocationScriptHash, addrToSlice(addr, err)
}
// Check for stake change script. Only stake-change-tagged
// pay-to-pubkey-hash and pay-to-script-hash are allowed.
if h := ExtractStakeChangePubKeyHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(h, params)
return STStakeChangePubKeyHash, addrToSlice(addr, err)
}
if h := ExtractStakeChangeScriptHashV0(pkScript); h != nil {
addr, err := stdaddr.NewAddressScriptHashV0FromHash(h, params)
return STStakeChangeScriptHash, addrToSlice(addr, err)
}
// Check for null data script.
if IsNullDataScriptV0(pkScript) {
// Null data scripts do not have an associated address.
return STNullData, nil
}
// Don't attempt to extract addresses for nonstandard transactions.
return STNonStandard, nil
}