scriptnum

package
v0.0.0-...-46f88e6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2023 License: ISC Imports: 3 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MaxInt32 = 1<<31 - 1
	MinInt32 = -1 << 31

	// DefaultScriptNumLen is the default number of bytes
	// data being interpreted as an integer may be.
	DefaultScriptNumLen = 4
)

Variables

This section is empty.

Functions

func CheckMinimalDataEncoding

func CheckMinimalDataEncoding(v []byte) er.R

CheckMinimalDataEncoding returns whether or not the passed byte array adheres to the minimal encoding requirements.

Types

type ScriptNum

type ScriptNum int64

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.

func MakeScriptNum

func MakeScriptNum(v []byte, requireMinimal bool, scriptNumLen int) (ScriptNum, er.R)

MakeScriptNum interprets the passed serialized bytes as an encoded integer and returns the result as a script number.

Since the consensus rules dictate that serialized bytes interpreted as ints are only allowed to be in the range determined by a maximum number of bytes, on a per opcode basis, an error will be returned when the provided bytes would result in a number outside of that range. In particular, the range for the vast majority of opcodes dealing with numeric values are limited to 4 bytes and therefore will pass that value to this function resulting in an allowed range of [-2^31 + 1, 2^31 - 1].

The requireMinimal flag causes an error to be returned if additional checks on the encoding determine it is not represented with the smallest possible number of bytes or is the negative 0 encoding, [0x80]. For example, consider the number 127. It could be encoded as [0x7f], [0x7f 0x00], [0x7f 0x00 0x00 ...], etc. All forms except [0x7f] will return an error with requireMinimal enabled.

The scriptNumLen is the maximum number of bytes the encoded value can be before an ErrStackNumberTooBig is returned. This effectively limits the range of allowed values. WARNING: Great care should be taken if passing a value larger than defaultScriptNumLen, which could lead to addition and multiplication overflows.

See the Bytes function documentation for example encodings.

func (ScriptNum) Bytes

func (n ScriptNum) Bytes() []byte

Bytes returns the number serialized as a little endian with a sign bit.

Example encodings:

   127 -> [0x7f]
  -127 -> [0xff]
   128 -> [0x80 0x00]
  -128 -> [0x80 0x80]
   129 -> [0x81 0x00]
  -129 -> [0x81 0x80]
   256 -> [0x00 0x01]
  -256 -> [0x00 0x81]
 32767 -> [0xff 0x7f]
-32767 -> [0xff 0xff]
 32768 -> [0x00 0x80 0x00]
-32768 -> [0x00 0x80 0x80]

func (ScriptNum) Int32

func (n ScriptNum) Int32() int32

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL