Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Commit

Permalink
Feat(BVM): change op1Add use uint256 (#1846)
Browse files Browse the repository at this point in the history
* Feat(BVM): change op1Add use uint256

* Feat(BVM): change op1Add use uint256

* Feat(BVM): change op1Add use uint256

* Feat(BVM): change op1Add use uint256

* Feat(BVM): change op1Add use uint256

* Feat(BVM): change op1Add use uint256

* Feat(BVM): change op1Add use uint256 and test

* Feat(BVM): change op1Add testcase
  • Loading branch information
bitstory authored Apr 1, 2021
1 parent 0edeef6 commit 6fa6884
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 83 deletions.
19 changes: 19 additions & 0 deletions math/checked/checked.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ package checked
import (
"errors"
"math"
"math/big"

"github.com/holiman/uint256"
)

var ErrOverflow = errors.New("arithmetic overflow")
Expand Down Expand Up @@ -266,3 +269,19 @@ func LshiftUint32(a, b uint32) (result uint32, ok bool) {
}
return a << uint(b), true
}

// NewUInt256 returns uint256
// with an integer overflow check.
func NewUInt256(a string) (num *uint256.Int, ok bool) {
bigIntNum, ok := new(big.Int).SetString(a, 10)
if !ok {
return nil, false
}

uint256Num, overflow := uint256.FromBig(bigIntNum)
if overflow {
return nil, false
}

return uint256Num, true
}
5 changes: 3 additions & 2 deletions protocol/vm/assemble.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"unicode"

"github.com/bytom/bytom/errors"
"github.com/bytom/bytom/math/checked"
)

// Assemble converts a string like "2 3 ADD 5 NUMEQUAL" into 0x525393559c.
Expand Down Expand Up @@ -90,8 +91,8 @@ func Assemble(s string) (res []byte, err error) {
b++
}
res = append(res, PushdataBytes(bytes)...)
} else if num, err := strconv.ParseInt(token, 10, 64); err == nil {
res = append(res, PushdataInt64(num)...)
} else if num, ok := checked.NewUInt256(token); ok {
res = append(res, PushdataBytes(BigIntBytes(num))...)
} else {
return nil, errors.Wrap(ErrToken, token)
}
Expand Down
1 change: 0 additions & 1 deletion protocol/vm/assemble_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ func TestAssemble(t *testing.T) {

for _, c := range cases {
got, gotErr := Assemble(c.plain)

if errors.Root(gotErr) != c.wantErr {
t.Errorf("Compile(%s) err = %v want %v", c.plain, errors.Root(gotErr), c.wantErr)
continue
Expand Down
6 changes: 6 additions & 0 deletions protocol/vm/mocks/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package mocks

// mocks data
var (
U256NumNegative1 = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)
17 changes: 14 additions & 3 deletions protocol/vm/numeric.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,26 @@ func op1Add(vm *virtualMachine) error {
if err != nil {
return err
}
n, err := vm.popInt64(true)

n, err := vm.popBigInt(true)
if err != nil {
return err
}
res, ok := checked.AddInt64(n, 1)

if n.Sign() < 0 {
return ErrRange
}

num, ok := checked.NewUInt256("1")
if !ok {
return ErrBadValue
}

if num.Add(n, num); num.Sign() < 0 {
return ErrRange
}
return vm.pushInt64(res, true)

return vm.pushBigInt(num, true)
}

func op1Sub(vm *virtualMachine) error {
Expand Down
51 changes: 5 additions & 46 deletions protocol/vm/numeric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package vm
import (
"fmt"
"math"
"math/big"
"testing"

"github.com/bytom/bytom/common"
"github.com/bytom/bytom/testutil"
)

Expand Down Expand Up @@ -489,53 +491,10 @@ func TestRangeErrs(t *testing.T) {
expectRangeErr bool
}{
{"0 1ADD", false},
{fmt.Sprintf("%d 1ADD", int64(math.MinInt64)), false},
{fmt.Sprintf("%d 1ADD", int64(math.MinInt64)), true},
{fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)-1), false},
{fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)), true},
{"0 1SUB", false},
{fmt.Sprintf("%d 1SUB", int64(math.MaxInt64)), false},
{fmt.Sprintf("%d 1SUB", int64(math.MinInt64)+1), false},
{fmt.Sprintf("%d 1SUB", int64(math.MinInt64)), true},
{"1 2MUL", false},
{fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2-1), false},
{fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2+1), true},
{fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2+1), false},
{fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2-1), true},
{"1 NEGATE", false},
{"-1 NEGATE", false},
{fmt.Sprintf("%d NEGATE", int64(math.MaxInt64)), false},
{fmt.Sprintf("%d NEGATE", int64(math.MinInt64)), true},
{"1 ABS", false},
{"-1 ABS", false},
{fmt.Sprintf("%d ABS", int64(math.MaxInt64)), false},
{fmt.Sprintf("%d ABS", int64(math.MinInt64)), true},
{"2 3 ADD", false},
{fmt.Sprintf("%d %d ADD", int64(math.MinInt64), int64(math.MaxInt64)), false},
{fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2-1, int64(math.MaxInt64)/2-2), false},
{fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2+1, int64(math.MaxInt64)/2+2), true},
{fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2+1, int64(math.MinInt64)/2+2), false},
{fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2-1, int64(math.MinInt64)/2-2), true},
{"2 3 SUB", false},
{fmt.Sprintf("1 %d SUB", int64(math.MaxInt64)), false},
{fmt.Sprintf("-1 %d SUB", int64(math.MinInt64)), false},
{fmt.Sprintf("1 %d SUB", int64(math.MinInt64)), true},
{fmt.Sprintf("-1 %d SUB", int64(math.MaxInt64)), false},
{fmt.Sprintf("-2 %d SUB", int64(math.MaxInt64)), true},
{"1 2 LSHIFT", false},
{"-1 2 LSHIFT", false},
{"-1 63 LSHIFT", false},
{"-1 64 LSHIFT", true},
{"0 64 LSHIFT", false},
{"1 62 LSHIFT", false},
{"1 63 LSHIFT", true},
{fmt.Sprintf("%d 0 LSHIFT", int64(math.MaxInt64)), false},
{fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)), true},
{fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)/2), false},
{fmt.Sprintf("%d 2 LSHIFT", int64(math.MaxInt64)/2), true},
{fmt.Sprintf("%d 0 LSHIFT", int64(math.MinInt64)), false},
{fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)), true},
{fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)/2), false},
{fmt.Sprintf("%d 2 LSHIFT", int64(math.MinInt64)/2), true},
{fmt.Sprintf("%s 1ADD", big.NewInt(0).SetBytes(common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")).String()), true},
{fmt.Sprintf("%s 1ADD", big.NewInt(0).SetBytes(common.Hex2Bytes("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")).String()), true},
}

for i, c := range cases {
Expand Down
3 changes: 1 addition & 2 deletions protocol/vm/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ func AsInt64(b []byte) (int64, error) {

// BigIntBytes conv big int to bytes, uint256 is version 1.1.1
func BigIntBytes(n *uint256.Int) []byte {
b := n.Bytes32()
return b[:]
return n.Bytes()
}

// AsBigInt conv bytes to big int
Expand Down
37 changes: 10 additions & 27 deletions protocol/vm/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,31 +87,16 @@ func TestBigIntBytes(t *testing.T) {
input []byte
num *big.Int
}{
{num: new(big.Int), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00}},
{num: new(big.Int).SetInt64(0), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00}},
{num: new(big.Int).SetInt64(1), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01}},
{num: new(big.Int).SetInt64(255), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff}},
{num: new(big.Int).SetInt64(256), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00}},
{num: new(big.Int).SetInt64(46657), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xb6, 0x41}},
{num: new(big.Int).SetInt64(1 << 32), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00}},
{num: new(big.Int), input: []byte{}},
{num: new(big.Int).SetInt64(0), input: []byte{}},
{num: new(big.Int).SetInt64(1), input: []byte{0x01}},
{num: new(big.Int).SetInt64(255), input: []byte{0xff}},
{num: new(big.Int).SetInt64(256), input: []byte{0x01, 0x00}},
{num: new(big.Int).SetInt64(46657), input: []byte{0xb6, 0x41}},
{num: new(big.Int).SetInt64(1 << 32), input: []byte{0x01, 0x00, 0x00, 0x00, 0x00}},
{
num: new(big.Int).Exp(new(big.Int).SetInt64(10), new(big.Int).SetInt64(32), nil),
input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0xee, 0x2d, 0x6d, 0x41, 0x5b, 0x85, 0xac, 0xef, 0x81, 0x00, 0x00, 0x00, 0x00},
input: []byte{0x04, 0xee, 0x2d, 0x6d, 0x41, 0x5b, 0x85, 0xac, 0xef, 0x81, 0x00, 0x00, 0x00, 0x00},
},
{num: new(big.Int).SetInt64(-1), input: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
Expand All @@ -128,7 +113,7 @@ func TestBigIntBytes(t *testing.T) {

gotData := BigIntBytes(fromBig)
if !bytes.Equal(gotData, test.input) {
t.Errorf("BigIntBytes(%s) = %x want %x", test.num.String(), gotData, []byte(test.input))
t.Errorf("BigIntBytes(%s) = %x want %x", test.num.String(), gotData, test.input)
}
}
}
Expand All @@ -139,9 +124,7 @@ func TestAsBigInt(t *testing.T) {
num *big.Int
}{
{num: new(big.Int), input: []byte{}},
{num: new(big.Int), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00}},
{num: new(big.Int), input: []byte{0x00}},
{num: new(big.Int).SetInt64(0), input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00}},
Expand Down
15 changes: 15 additions & 0 deletions protocol/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"io"
"strings"

"github.com/holiman/uint256"

"github.com/bytom/bytom/errors"
)

Expand Down Expand Up @@ -158,6 +160,10 @@ func (vm *virtualMachine) pushInt64(n int64, deferred bool) error {
return vm.push(Int64Bytes(n), deferred)
}

func (vm *virtualMachine) pushBigInt(n *uint256.Int, deferred bool) error {
return vm.push(BigIntBytes(n), deferred)
}

func (vm *virtualMachine) pop(deferred bool) ([]byte, error) {
if len(vm.dataStack) == 0 {
return nil, ErrDataStackUnderflow
Expand All @@ -184,6 +190,15 @@ func (vm *virtualMachine) popInt64(deferred bool) (int64, error) {
return n, err
}

func (vm *virtualMachine) popBigInt(deferred bool) (*uint256.Int, error) {
bytes, err := vm.pop(deferred)
if err != nil {
return nil, err
}

return AsBigInt(bytes)
}

func (vm *virtualMachine) top() ([]byte, error) {
if len(vm.dataStack) == 0 {
return nil, ErrDataStackUnderflow
Expand Down
5 changes: 3 additions & 2 deletions protocol/vm/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing/quick"

"github.com/bytom/bytom/errors"
"github.com/bytom/bytom/protocol/vm/mocks"
"github.com/bytom/bytom/testutil"
)

Expand Down Expand Up @@ -50,8 +51,8 @@ func doOKNotOK(t *testing.T, expectOK bool) {
{"XOR 0x05ff EQUAL", [][]byte{{0x03, 0xff}, {0x06}}},

// numeric and logical ops
{"1ADD 2 NUMEQUAL", [][]byte{Int64Bytes(1)}},
{"1ADD 0 NUMEQUAL", [][]byte{Int64Bytes(-1)}},
{"1ADD 2 NUMEQUAL", [][]byte{{0x01}}},
{"1ADD 0 NUMEQUAL", [][]byte{mocks.U256NumNegative1}},

{"1SUB 1 NUMEQUAL", [][]byte{Int64Bytes(2)}},
{"1SUB -1 NUMEQUAL", [][]byte{Int64Bytes(0)}},
Expand Down

0 comments on commit 6fa6884

Please sign in to comment.