/
consensus.go
288 lines (252 loc) · 10 KB
/
consensus.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
// Copyright (c) 2015-2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package txscript
import (
"fmt"
"github.com/EXCCoin/exccd/dcrec/secp256k1/v4"
)
const (
// LockTimeThreshold is the number below which a lock time is
// interpreted to be a block number. Since an average of one block
// is generated per 10 minutes, this allows blocks for about 9,512
// years.
LockTimeThreshold = 5e8 // Tue Nov 5 00:53:20 1985 UTC
)
// CheckSignatureEncoding returns whether or not the passed signature adheres to
// the strict encoding requirements.
func CheckSignatureEncoding(sig []byte) error {
// The format of a DER encoded signature is as follows:
//
// 0x30 <total length> 0x02 <length of R> <R> 0x02 <length of S> <S>
// - 0x30 is the ASN.1 identifier for a sequence
// - Total length is 1 byte and specifies length of all remaining data
// - 0x02 is the ASN.1 identifier that specifies an integer follows
// - Length of R is 1 byte and specifies how many bytes R occupies
// - R is the arbitrary length big-endian encoded number which
// represents the R value of the signature. DER encoding dictates
// that the value must be encoded using the minimum possible number
// of bytes. This implies the first byte can only be null if the
// highest bit of the next byte is set in order to prevent it from
// being interpreted as a negative number.
// - 0x02 is once again the ASN.1 integer identifier
// - Length of S is 1 byte and specifies how many bytes S occupies
// - S is the arbitrary length big-endian encoded number which
// represents the S value of the signature. The encoding rules are
// identical as those for R.
const (
asn1SequenceID = 0x30
asn1IntegerID = 0x02
// minSigLen is the minimum length of a DER encoded signature and is
// when both R and S are 1 byte each.
//
// 0x30 + <1-byte> + 0x02 + 0x01 + <byte> + 0x2 + 0x01 + <byte>
minSigLen = 8
// maxSigLen is the maximum length of a DER encoded signature and is
// when both R and S are 33 bytes each. It is 33 bytes because a
// 256-bit integer requires 32 bytes and an additional leading null byte
// might required if the high bit is set in the value.
//
// 0x30 + <1-byte> + 0x02 + 0x21 + <33 bytes> + 0x2 + 0x21 + <33 bytes>
maxSigLen = 72
// sequenceOffset is the byte offset within the signature of the
// expected ASN.1 sequence identifier.
sequenceOffset = 0
// dataLenOffset is the byte offset within the signature of the expected
// total length of all remaining data in the signature.
dataLenOffset = 1
// rTypeOffset is the byte offset within the signature of the ASN.1
// identifier for R and is expected to indicate an ASN.1 integer.
rTypeOffset = 2
// rLenOffset is the byte offset within the signature of the length of
// R.
rLenOffset = 3
// rOffset is the byte offset within the signature of R.
rOffset = 4
)
// The signature must adhere to the minimum and maximum allowed length.
sigLen := len(sig)
if sigLen < minSigLen {
str := fmt.Sprintf("malformed signature: too short: %d < %d", sigLen,
minSigLen)
return scriptError(ErrSigTooShort, str)
}
if sigLen > maxSigLen {
str := fmt.Sprintf("malformed signature: too long: %d > %d", sigLen,
maxSigLen)
return scriptError(ErrSigTooLong, str)
}
// The signature must start with the ASN.1 sequence identifier.
if sig[sequenceOffset] != asn1SequenceID {
str := fmt.Sprintf("malformed signature: format has wrong type: %#x",
sig[sequenceOffset])
return scriptError(ErrSigInvalidSeqID, str)
}
// The signature must indicate the correct amount of data for all elements
// related to R and S.
if int(sig[dataLenOffset]) != sigLen-2 {
str := fmt.Sprintf("malformed signature: bad length: %d != %d",
sig[dataLenOffset], sigLen-2)
return scriptError(ErrSigInvalidDataLen, str)
}
// Calculate the offsets of the elements related to S and ensure S is inside
// the signature.
//
// rLen specifies the length of the big-endian encoded number which
// represents the R value of the signature.
//
// sTypeOffset is the offset of the ASN.1 identifier for S and, like its R
// counterpart, is expected to indicate an ASN.1 integer.
//
// sLenOffset and sOffset are the byte offsets within the signature of the
// length of S and S itself, respectively.
rLen := int(sig[rLenOffset])
sTypeOffset := rOffset + rLen
sLenOffset := sTypeOffset + 1
if sTypeOffset >= sigLen {
str := "malformed signature: S type indicator missing"
return scriptError(ErrSigMissingSTypeID, str)
}
if sLenOffset >= sigLen {
str := "malformed signature: S length missing"
return scriptError(ErrSigMissingSLen, str)
}
// The lengths of R and S must match the overall length of the signature.
//
// sLen specifies the length of the big-endian encoded number which
// represents the S value of the signature.
sOffset := sLenOffset + 1
sLen := int(sig[sLenOffset])
if sOffset+sLen != sigLen {
str := "malformed signature: invalid S length"
return scriptError(ErrSigInvalidSLen, str)
}
// R elements must be ASN.1 integers.
if sig[rTypeOffset] != asn1IntegerID {
str := fmt.Sprintf("malformed signature: R integer marker: %#x != %#x",
sig[rTypeOffset], asn1IntegerID)
return scriptError(ErrSigInvalidRIntID, str)
}
// Zero-length integers are not allowed for R.
if rLen == 0 {
str := "malformed signature: R length is zero"
return scriptError(ErrSigZeroRLen, str)
}
// R must not be negative.
if sig[rOffset]&0x80 != 0 {
str := "malformed signature: R is negative"
return scriptError(ErrSigNegativeR, str)
}
// Null bytes at the start of R are not allowed, unless R would otherwise be
// interpreted as a negative number.
if rLen > 1 && sig[rOffset] == 0x00 && sig[rOffset+1]&0x80 == 0 {
str := "malformed signature: R value has too much padding"
return scriptError(ErrSigTooMuchRPadding, str)
}
// S elements must be ASN.1 integers.
if sig[sTypeOffset] != asn1IntegerID {
str := fmt.Sprintf("malformed signature: S integer marker: %#x != %#x",
sig[sTypeOffset], asn1IntegerID)
return scriptError(ErrSigInvalidSIntID, str)
}
// Zero-length integers are not allowed for S.
if sLen == 0 {
str := "malformed signature: S length is zero"
return scriptError(ErrSigZeroSLen, str)
}
// S must not be negative.
if sig[sOffset]&0x80 != 0 {
str := "malformed signature: S is negative"
return scriptError(ErrSigNegativeS, str)
}
// Null bytes at the start of S are not allowed, unless S would otherwise be
// interpreted as a negative number.
if sLen > 1 && sig[sOffset] == 0x00 && sig[sOffset+1]&0x80 == 0 {
str := "malformed signature: S value has too much padding"
return scriptError(ErrSigTooMuchSPadding, str)
}
// Strip leading zeroes from S.
sBytes := sig[sOffset : sOffset+sLen]
for len(sBytes) > 0 && sBytes[0] == 0x00 {
sBytes = sBytes[1:]
}
// Verify the S value is <= half the order of the curve. This check is done
// because when it is higher, the complement modulo the order can be used
// instead which is a shorter encoding by 1 byte.
//
// Also notice the check for the maximum number of bytes is required because
// SetByteSlice truncates as noted in its comment so it could otherwise fail
// to detect the overflow.
var s secp256k1.ModNScalar
if len(sBytes) > 32 {
str := "non-canonical signature: S is larger than 256 bits"
return scriptError(ErrSigHighS, str)
}
if overflow := s.SetByteSlice(sBytes); overflow {
str := "non-canonical signature: S >= group order"
return scriptError(ErrSigHighS, str)
}
if s.IsOverHalfOrder() {
str := "non-canonical signature: S > group half order"
return scriptError(ErrSigHighS, str)
}
return nil
}
// IsStrictSignatureEncoding returns false if the passed signature does not
// adhere to the strict encoding requirements.
func IsStrictSignatureEncoding(signature []byte) bool {
return CheckSignatureEncoding(signature) == nil
}
// CheckPubKeyEncoding returns an error if the passed public key does not
// adhere to the strict encoding requirements.
func CheckPubKeyEncoding(pubKey []byte) error {
if !isStrictPubKeyEncoding(pubKey) {
return scriptError(ErrPubKeyType, "unsupported public key type")
}
return nil
}
// CheckHashTypeEncoding returns whether or not the passed hashtype adheres to
// the strict encoding requirements.
func CheckHashTypeEncoding(hashType SigHashType) error {
sigHashType := hashType & ^SigHashAnyOneCanPay
if sigHashType < SigHashAll || sigHashType > SigHashSingle {
str := fmt.Sprintf("invalid hash type 0x%x", hashType)
return scriptError(ErrInvalidSigHashType, str)
}
return nil
}
// IsStrictCompressedPubKeyEncoding returns whether or not the passed public
// key adheres to the strict compressed encoding requirements.
func IsStrictCompressedPubKeyEncoding(pubKey []byte) bool {
if len(pubKey) == 33 && (pubKey[0] == 0x02 || pubKey[0] == 0x03) {
// Compressed
return true
}
return false
}
// IsStrictNullData returns whether or not the passed data is an OP_RETURN
// followed by specified length data push. It explicitly verifies that the
// opcode is identical to the required length. This function will always return
// false for required lengths > 75 bytes.
func IsStrictNullData(scriptVersion uint16, script []byte, requiredLen uint32) bool {
// The only currently supported script version is 0.
if scriptVersion != 0 {
return false
}
// The script can't possibly be a null data script if it doesn't start
// with OP_RETURN. Fail fast to avoid more work below.
if len(script) < 1 || script[0] != OP_RETURN {
return false
}
// Allow bare OP_RETURN when the required length is 0.
if len(script) == 1 && requiredLen == 0 {
return true
}
// OP_RETURN followed by data push of the required size.
tokenizer := MakeScriptTokenizer(scriptVersion, script[1:])
return tokenizer.Next() && tokenizer.Done() &&
isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) &&
((IsSmallInt(tokenizer.Opcode()) && requiredLen == 1) ||
(tokenizer.Opcode() <= OP_DATA_75 &&
uint32(len(tokenizer.Data())) == requiredLen))
}