parser: Correctly parse heights from script-encoded int64 values
This commit is contained in:
parent
4794bca46e
commit
5acfb9af34
|
@ -62,21 +62,15 @@ func (b *block) GetHeight() int {
|
||||||
return b.height
|
return b.height
|
||||||
}
|
}
|
||||||
coinbaseScript := bytestring.String(b.vtx[0].transparentInputs[0].ScriptSig)
|
coinbaseScript := bytestring.String(b.vtx[0].transparentInputs[0].ScriptSig)
|
||||||
var heightByte byte
|
var heightNum int64
|
||||||
if ok := coinbaseScript.ReadByte(&heightByte); !ok {
|
if ok := coinbaseScript.ReadScriptInt64(&heightNum); !ok {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
heightLen := int(heightByte)
|
if heightNum < 0 {
|
||||||
var heightBytes = make([]byte, heightLen)
|
|
||||||
if ok := coinbaseScript.ReadBytes(&heightBytes, heightLen); !ok {
|
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
// uint32 should last us a while (Nov 2018)
|
// uint32 should last us a while (Nov 2018)
|
||||||
var blockHeight uint32
|
blockHeight := uint32(heightNum)
|
||||||
for i := heightLen - 1; i >= 0; i-- {
|
|
||||||
blockHeight <<= 8
|
|
||||||
blockHeight = blockHeight | uint32(heightBytes[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
if blockHeight == genesisTargetDifficulty {
|
if blockHeight == genesisTargetDifficulty {
|
||||||
blockHeight = 0
|
blockHeight = 0
|
||||||
|
|
|
@ -9,6 +9,11 @@ import (
|
||||||
|
|
||||||
const MAX_COMPACT_SIZE uint64 = 0x02000000
|
const MAX_COMPACT_SIZE uint64 = 0x02000000
|
||||||
|
|
||||||
|
const OP_0 uint8 = 0x00
|
||||||
|
const OP_1NEGATE uint8 = 0x4f
|
||||||
|
const OP_1 uint8 = 0x51
|
||||||
|
const OP_16 uint8 = 0x60
|
||||||
|
|
||||||
// String represents a string of bytes and provides methods for parsing values
|
// String represents a string of bytes and provides methods for parsing values
|
||||||
// from it.
|
// from it.
|
||||||
type String []byte
|
type String []byte
|
||||||
|
@ -194,3 +199,42 @@ func (s *String) ReadUint64(out *uint64) bool {
|
||||||
uint64(v[4])<<32 | uint64(v[5])<<40 | uint64(v[6])<<48 | uint64(v[7])<<56
|
uint64(v[4])<<32 | uint64(v[5])<<40 | uint64(v[6])<<48 | uint64(v[7])<<56
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadScriptInt64 reads and interprets a Bitcoin-custom compact integer
|
||||||
|
// encoding used for int64 numbers in scripts.
|
||||||
|
//
|
||||||
|
// See https://github.com/zcash/zcash/blob/4df60f4b334dd9aee5df3a481aee63f40b52654b/src/script/script.h#L363-L378
|
||||||
|
func (s *String) ReadScriptInt64(num *int64) bool {
|
||||||
|
// First byte is either an integer opcode, or the number of bytes in the
|
||||||
|
// number.
|
||||||
|
firstBytes := s.read(1)
|
||||||
|
if firstBytes == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
firstByte := firstBytes[0]
|
||||||
|
|
||||||
|
var number uint64
|
||||||
|
|
||||||
|
if firstByte == OP_1NEGATE {
|
||||||
|
*num = -1
|
||||||
|
return true
|
||||||
|
} else if firstByte == OP_0 {
|
||||||
|
number = 0
|
||||||
|
} else if firstByte >= OP_1 && firstByte <= OP_16 {
|
||||||
|
number = uint64(firstByte) - uint64(OP_1 - 1)
|
||||||
|
} else {
|
||||||
|
numLen := int(firstByte)
|
||||||
|
// expect little endian int of varying size
|
||||||
|
numBytes := s.read(numLen)
|
||||||
|
if numBytes == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := numLen - 1; i >= 0; i-- {
|
||||||
|
number <<= 8
|
||||||
|
number = number | uint64(numBytes[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*num = int64(number)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue