mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-18 20:54:20 +01:00
* covenant based tx builder * remove relative time delta * txbuilder/covenant add leaf boolean in node * txbuilder/covenant final version * support covenantType * add GetLeafOutputScript * remove printLn * fix linting * Update asp/internal/app-config/config.go Co-authored-by: João Bordalo <bordalix@users.noreply.github.com> Signed-off-by: Louis Singer <41042567+louisinger@users.noreply.github.com> --------- Signed-off-by: Louis Singer <41042567+louisinger@users.noreply.github.com> Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>
107 lines
3.9 KiB
Go
107 lines
3.9 KiB
Go
// Copyright (c) 2015-2017 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package txbuilder
|
|
|
|
const (
|
|
maxInt32 = 1<<31 - 1
|
|
minInt32 = -1 << 31
|
|
)
|
|
|
|
// scriptNum represents a numeric value used in the scripting engine with
|
|
// special handling to deal with the subtle semantics required by consensus.
|
|
//
|
|
// All numbers are stored on the data and alternate stacks encoded as little
|
|
// endian with a sign bit. All numeric opcodes such as OP_ADD, OP_SUB,
|
|
// and OP_MUL, are only allowed to operate on 4-byte integers in the range
|
|
// [-2^31 + 1, 2^31 - 1], however the results of numeric operations may overflow
|
|
// and remain valid so long as they are not used as inputs to other numeric
|
|
// operations or otherwise interpreted as an integer.
|
|
//
|
|
// For example, it is possible for OP_ADD to have 2^31 - 1 for its two operands
|
|
// resulting 2^32 - 2, which overflows, but is still pushed to the stack as the
|
|
// result of the addition. That value can then be used as input to OP_VERIFY
|
|
// which will succeed because the data is being interpreted as a boolean.
|
|
// However, if that same value were to be used as input to another numeric
|
|
// opcode, such as OP_SUB, it must fail.
|
|
//
|
|
// This type handles the aforementioned requirements by storing all numeric
|
|
// operation results as an int64 to handle overflow and provides the Bytes
|
|
// method to get the serialized representation (including values that overflow).
|
|
//
|
|
// Then, whenever data is interpreted as an integer, it is converted to this
|
|
// type by using the MakeScriptNum function which will return an error if the
|
|
// number is out of range or not minimally encoded depending on parameters.
|
|
// Since all numeric opcodes involve pulling data from the stack and
|
|
// interpreting it as an integer, it provides the required behavior.
|
|
type scriptNum int64
|
|
|
|
// Bytes returns the number serialized as a little endian with a sign bit.
|
|
func (n scriptNum) Bytes() []byte {
|
|
// Zero encodes as an empty byte slice.
|
|
if n == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Take the absolute value and keep track of whether it was originally
|
|
// negative.
|
|
isNegative := n < 0
|
|
if isNegative {
|
|
n = -n
|
|
}
|
|
|
|
// Encode to little endian. The maximum number of encoded bytes is 9
|
|
// (8 bytes for max int64 plus a potential byte for sign extension).
|
|
result := make([]byte, 0, 9)
|
|
for n > 0 {
|
|
result = append(result, byte(n&0xff))
|
|
n >>= 8
|
|
}
|
|
|
|
// When the most significant byte already has the high bit set, an
|
|
// additional high byte is required to indicate whether the number is
|
|
// negative or positive. The additional byte is removed when converting
|
|
// back to an integral and its high bit is used to denote the sign.
|
|
//
|
|
// Otherwise, when the most significant byte does not already have the
|
|
// high bit set, use it to indicate the value is negative, if needed.
|
|
if result[len(result)-1]&0x80 != 0 {
|
|
extraByte := byte(0x00)
|
|
if isNegative {
|
|
extraByte = 0x80
|
|
}
|
|
result = append(result, extraByte)
|
|
|
|
} else if isNegative {
|
|
result[len(result)-1] |= 0x80
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// Int32 returns the script number clamped to a valid int32. That is to say
|
|
// when the script number is higher than the max allowed int32, the max int32
|
|
// value is returned and vice versa for the minimum value. Note that this
|
|
// behavior is different from a simple int32 cast because that truncates
|
|
// and the consensus rules dictate numbers which are directly cast to ints
|
|
// provide this behavior.
|
|
//
|
|
// In practice, for most opcodes, the number should never be out of range since
|
|
// it will have been created with MakeScriptNum using the defaultScriptLen
|
|
// value, which rejects them. In case something in the future ends up calling
|
|
// this function against the result of some arithmetic, which IS allowed to be
|
|
// out of range before being reinterpreted as an integer, this will provide the
|
|
// correct behavior.
|
|
func (n scriptNum) Int32() int32 {
|
|
if n > maxInt32 {
|
|
return maxInt32
|
|
}
|
|
|
|
if n < minInt32 {
|
|
return minInt32
|
|
}
|
|
|
|
return int32(n)
|
|
}
|