scriptnum_test.go raw

   1  package txscript
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/hex"
   6  	"testing"
   7  )
   8  
   9  // hexToBytes converts the passed hex string into bytes and will panic if there is an error. This is only provided for
  10  // the hard-coded constants so errors in the source code can be detected. It will only (and must only) be called with
  11  // hard-coded values.
  12  func hexToBytes(s string) []byte {
  13  	b, e := hex.DecodeString(s)
  14  	if e != nil {
  15  		panic("invalid hex in source file: " + s)
  16  	}
  17  	return b
  18  }
  19  
  20  // TestScriptNumBytes ensures that converting from integral script numbers to byte representations works as expected.
  21  func TestScriptNumBytes(t *testing.T) {
  22  	t.Parallel()
  23  	tests := []struct {
  24  		num        scriptNum
  25  		serialized []byte
  26  	}{
  27  		{0, nil},
  28  		{1, hexToBytes("01")},
  29  		{-1, hexToBytes("81")},
  30  		{127, hexToBytes("7f")},
  31  		{-127, hexToBytes("ff")},
  32  		{128, hexToBytes("8000")},
  33  		{-128, hexToBytes("8080")},
  34  		{129, hexToBytes("8100")},
  35  		{-129, hexToBytes("8180")},
  36  		{256, hexToBytes("0001")},
  37  		{-256, hexToBytes("0081")},
  38  		{32767, hexToBytes("ff7f")},
  39  		{-32767, hexToBytes("ffff")},
  40  		{32768, hexToBytes("008000")},
  41  		{-32768, hexToBytes("008080")},
  42  		{65535, hexToBytes("ffff00")},
  43  		{-65535, hexToBytes("ffff80")},
  44  		{524288, hexToBytes("000008")},
  45  		{-524288, hexToBytes("000088")},
  46  		{7340032, hexToBytes("000070")},
  47  		{-7340032, hexToBytes("0000f0")},
  48  		{8388608, hexToBytes("00008000")},
  49  		{-8388608, hexToBytes("00008080")},
  50  		{2147483647, hexToBytes("ffffff7f")},
  51  		{-2147483647, hexToBytes("ffffffff")},
  52  		// Values that are out of range for data that is interpreted as numbers, but are allowed as the result of
  53  		// numeric operations.
  54  		{2147483648, hexToBytes("0000008000")},
  55  		{-2147483648, hexToBytes("0000008080")},
  56  		{2415919104, hexToBytes("0000009000")},
  57  		{-2415919104, hexToBytes("0000009080")},
  58  		{4294967295, hexToBytes("ffffffff00")},
  59  		{-4294967295, hexToBytes("ffffffff80")},
  60  		{4294967296, hexToBytes("0000000001")},
  61  		{-4294967296, hexToBytes("0000000081")},
  62  		{281474976710655, hexToBytes("ffffffffffff00")},
  63  		{-281474976710655, hexToBytes("ffffffffffff80")},
  64  		{72057594037927935, hexToBytes("ffffffffffffff00")},
  65  		{-72057594037927935, hexToBytes("ffffffffffffff80")},
  66  		{9223372036854775807, hexToBytes("ffffffffffffff7f")},
  67  		{-9223372036854775807, hexToBytes("ffffffffffffffff")},
  68  	}
  69  	for _, test := range tests {
  70  		gotBytes := test.num.Bytes()
  71  		if !bytes.Equal(gotBytes, test.serialized) {
  72  			t.Errorf("Hash: did not get expected bytes for %d - "+
  73  				"got %x, want %x", test.num, gotBytes,
  74  				test.serialized,
  75  			)
  76  			continue
  77  		}
  78  	}
  79  }
  80  
  81  // TestMakeScriptNum ensures that converting from byte representations to integral script numbers works as expected.
  82  func TestMakeScriptNum(t *testing.T) {
  83  	t.Parallel()
  84  	// Errors used in the tests below defined here for convenience and to keep the horizontal test size shorter.
  85  	errNumTooBig := scriptError(ErrNumberTooBig, "")
  86  	errMinimalData := scriptError(ErrMinimalData, "")
  87  	tests := []struct {
  88  		serialized      []byte
  89  		num             scriptNum
  90  		numLen          int
  91  		minimalEncoding bool
  92  		err             error
  93  	}{
  94  		// Minimal encoding must reject negative 0.
  95  		{hexToBytes("80"), 0, defaultScriptNumLen, true, errMinimalData},
  96  		// Minimally encoded valid values with minimal encoding flag. Should not error and return expected integral
  97  		// number.
  98  		{nil, 0, defaultScriptNumLen, true, nil},
  99  		{hexToBytes("01"), 1, defaultScriptNumLen, true, nil},
 100  		{hexToBytes("81"), -1, defaultScriptNumLen, true, nil},
 101  		{hexToBytes("7f"), 127, defaultScriptNumLen, true, nil},
 102  		{hexToBytes("ff"), -127, defaultScriptNumLen, true, nil},
 103  		{hexToBytes("8000"), 128, defaultScriptNumLen, true, nil},
 104  		{hexToBytes("8080"), -128, defaultScriptNumLen, true, nil},
 105  		{hexToBytes("8100"), 129, defaultScriptNumLen, true, nil},
 106  		{hexToBytes("8180"), -129, defaultScriptNumLen, true, nil},
 107  		{hexToBytes("0001"), 256, defaultScriptNumLen, true, nil},
 108  		{hexToBytes("0081"), -256, defaultScriptNumLen, true, nil},
 109  		{hexToBytes("ff7f"), 32767, defaultScriptNumLen, true, nil},
 110  		{hexToBytes("ffff"), -32767, defaultScriptNumLen, true, nil},
 111  		{hexToBytes("008000"), 32768, defaultScriptNumLen, true, nil},
 112  		{hexToBytes("008080"), -32768, defaultScriptNumLen, true, nil},
 113  		{hexToBytes("ffff00"), 65535, defaultScriptNumLen, true, nil},
 114  		{hexToBytes("ffff80"), -65535, defaultScriptNumLen, true, nil},
 115  		{hexToBytes("000008"), 524288, defaultScriptNumLen, true, nil},
 116  		{hexToBytes("000088"), -524288, defaultScriptNumLen, true, nil},
 117  		{hexToBytes("000070"), 7340032, defaultScriptNumLen, true, nil},
 118  		{hexToBytes("0000f0"), -7340032, defaultScriptNumLen, true, nil},
 119  		{hexToBytes("00008000"), 8388608, defaultScriptNumLen, true, nil},
 120  		{hexToBytes("00008080"), -8388608, defaultScriptNumLen, true, nil},
 121  		{hexToBytes("ffffff7f"), 2147483647, defaultScriptNumLen, true, nil},
 122  		{hexToBytes("ffffffff"), -2147483647, defaultScriptNumLen, true, nil},
 123  		{hexToBytes("ffffffff7f"), 549755813887, 5, true, nil},
 124  		{hexToBytes("ffffffffff"), -549755813887, 5, true, nil},
 125  		{hexToBytes("ffffffffffffff7f"), 9223372036854775807, 8, true, nil},
 126  		{hexToBytes("ffffffffffffffff"), -9223372036854775807, 8, true, nil},
 127  		{hexToBytes("ffffffffffffffff7f"), -1, 9, true, nil},
 128  		{hexToBytes("ffffffffffffffffff"), 1, 9, true, nil},
 129  		{hexToBytes("ffffffffffffffffff7f"), -1, 10, true, nil},
 130  		{hexToBytes("ffffffffffffffffffff"), 1, 10, true, nil},
 131  		// Minimally encoded values that are out of range for data that is interpreted as script numbers with the
 132  		// minimal encoding flag set.  Should error and return 0.
 133  		{hexToBytes("0000008000"), 0, defaultScriptNumLen, true, errNumTooBig},
 134  		{hexToBytes("0000008080"), 0, defaultScriptNumLen, true, errNumTooBig},
 135  		{hexToBytes("0000009000"), 0, defaultScriptNumLen, true, errNumTooBig},
 136  		{hexToBytes("0000009080"), 0, defaultScriptNumLen, true, errNumTooBig},
 137  		{hexToBytes("ffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
 138  		{hexToBytes("ffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
 139  		{hexToBytes("0000000001"), 0, defaultScriptNumLen, true, errNumTooBig},
 140  		{hexToBytes("0000000081"), 0, defaultScriptNumLen, true, errNumTooBig},
 141  		{hexToBytes("ffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
 142  		{hexToBytes("ffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
 143  		{hexToBytes("ffffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
 144  		{hexToBytes("ffffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
 145  		{hexToBytes("ffffffffffffff7f"), 0, defaultScriptNumLen, true, errNumTooBig},
 146  		{hexToBytes("ffffffffffffffff"), 0, defaultScriptNumLen, true, errNumTooBig},
 147  		// Non-minimally encoded, but otherwise valid values with minimal encoding flag.  Should error and return 0.
 148  		{hexToBytes("00"), 0, defaultScriptNumLen, true, errMinimalData},       // 0
 149  		{hexToBytes("0100"), 0, defaultScriptNumLen, true, errMinimalData},     // 1
 150  		{hexToBytes("7f00"), 0, defaultScriptNumLen, true, errMinimalData},     // 127
 151  		{hexToBytes("800000"), 0, defaultScriptNumLen, true, errMinimalData},   // 128
 152  		{hexToBytes("810000"), 0, defaultScriptNumLen, true, errMinimalData},   // 129
 153  		{hexToBytes("000100"), 0, defaultScriptNumLen, true, errMinimalData},   // 256
 154  		{hexToBytes("ff7f00"), 0, defaultScriptNumLen, true, errMinimalData},   // 32767
 155  		{hexToBytes("00800000"), 0, defaultScriptNumLen, true, errMinimalData}, // 32768
 156  		{hexToBytes("ffff0000"), 0, defaultScriptNumLen, true, errMinimalData}, // 65535
 157  		{hexToBytes("00000800"), 0, defaultScriptNumLen, true, errMinimalData}, // 524288
 158  		{hexToBytes("00007000"), 0, defaultScriptNumLen, true, errMinimalData}, // 7340032
 159  		{hexToBytes("0009000100"), 0, 5, true, errMinimalData},                 // 16779520
 160  		// Non-minimally encoded, but otherwise valid values without minimal encoding flag.  Should not error and return
 161  		// expected integral number.
 162  		{hexToBytes("00"), 0, defaultScriptNumLen, false, nil},
 163  		{hexToBytes("0100"), 1, defaultScriptNumLen, false, nil},
 164  		{hexToBytes("7f00"), 127, defaultScriptNumLen, false, nil},
 165  		{hexToBytes("800000"), 128, defaultScriptNumLen, false, nil},
 166  		{hexToBytes("810000"), 129, defaultScriptNumLen, false, nil},
 167  		{hexToBytes("000100"), 256, defaultScriptNumLen, false, nil},
 168  		{hexToBytes("ff7f00"), 32767, defaultScriptNumLen, false, nil},
 169  		{hexToBytes("00800000"), 32768, defaultScriptNumLen, false, nil},
 170  		{hexToBytes("ffff0000"), 65535, defaultScriptNumLen, false, nil},
 171  		{hexToBytes("00000800"), 524288, defaultScriptNumLen, false, nil},
 172  		{hexToBytes("00007000"), 7340032, defaultScriptNumLen, false, nil},
 173  		{hexToBytes("0009000100"), 16779520, 5, false, nil},
 174  	}
 175  	for _, test := range tests {
 176  		// Ensure the error code is of the expected type and the error code matches the value specified in the test
 177  		// instance.
 178  		gotNum, e := makeScriptNum(test.serialized, test.minimalEncoding,
 179  			test.numLen,
 180  		)
 181  		if e = tstCheckScriptError(e, test.err); e != nil {
 182  			t.Errorf("makeScriptNum(%#x): %v", test.serialized, e)
 183  			continue
 184  		}
 185  		if gotNum != test.num {
 186  			t.Errorf("makeScriptNum(%#x): did not get expected "+
 187  				"number - got %d, want %d", test.serialized,
 188  				gotNum, test.num,
 189  			)
 190  			continue
 191  		}
 192  	}
 193  }
 194  
 195  // TestScriptNumInt32 ensures that the Int32 function on script number behaves as expected.
 196  func TestScriptNumInt32(t *testing.T) {
 197  	t.Parallel()
 198  	tests := []struct {
 199  		in   scriptNum
 200  		want int32
 201  	}{
 202  		// Values inside the valid int32 range are just the values themselves cast to an int32.
 203  		{0, 0},
 204  		{1, 1},
 205  		{-1, -1},
 206  		{127, 127},
 207  		{-127, -127},
 208  		{128, 128},
 209  		{-128, -128},
 210  		{129, 129},
 211  		{-129, -129},
 212  		{256, 256},
 213  		{-256, -256},
 214  		{32767, 32767},
 215  		{-32767, -32767},
 216  		{32768, 32768},
 217  		{-32768, -32768},
 218  		{65535, 65535},
 219  		{-65535, -65535},
 220  		{524288, 524288},
 221  		{-524288, -524288},
 222  		{7340032, 7340032},
 223  		{-7340032, -7340032},
 224  		{8388608, 8388608},
 225  		{-8388608, -8388608},
 226  		{2147483647, 2147483647},
 227  		{-2147483647, -2147483647},
 228  		{-2147483648, -2147483648},
 229  		// Values outside of the valid int32 range are limited to int32.
 230  		{2147483648, 2147483647},
 231  		{-2147483649, -2147483648},
 232  		{1152921504606846975, 2147483647},
 233  		{-1152921504606846975, -2147483648},
 234  		{2305843009213693951, 2147483647},
 235  		{-2305843009213693951, -2147483648},
 236  		{4611686018427387903, 2147483647},
 237  		{-4611686018427387903, -2147483648},
 238  		{9223372036854775807, 2147483647},
 239  		{-9223372036854775808, -2147483648},
 240  	}
 241  	for _, test := range tests {
 242  		got := test.in.Int32()
 243  		if got != test.want {
 244  			t.Errorf("Int32: did not get expected value for %d - "+
 245  				"got %d, want %d", test.in, got, test.want,
 246  			)
 247  			continue
 248  		}
 249  	}
 250  }
 251