github.com/btcsuite/btcd@v0.24.0/txscript/scriptnum_test.go (about)

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