From 1613ba12dd8279511acd1997c2d85f82663ac38b Mon Sep 17 00:00:00 2001 From: Meng-Ying Yang Date: Mon, 15 Apr 2019 12:09:23 +0800 Subject: core: vm: sqlvm: add built-in function BLOCK_GASLIMIT() --- core/vm/sqlvm/runtime/functions.go | 21 +++++++++++++++ core/vm/sqlvm/runtime/functions_test.go | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) (limited to 'core') diff --git a/core/vm/sqlvm/runtime/functions.go b/core/vm/sqlvm/runtime/functions.go index c21d1da19..c180f1714 100644 --- a/core/vm/sqlvm/runtime/functions.go +++ b/core/vm/sqlvm/runtime/functions.go @@ -1,6 +1,9 @@ package runtime import ( + "fmt" + "math" + "github.com/dexon-foundation/decimal" "github.com/dexon-foundation/dexon/core/vm/sqlvm/ast" @@ -15,6 +18,7 @@ const ( BLOCKNUMBER = "BLOCK_NUMBER" BLOCKTIMESTAMP = "BLOCK_TIMESTAMP" BLOCKCOINBASE = "BLOCK_COINBASE" + BLOCKGASLIMIT = "BLOCK_GAS_LIMIT" NOW = "NOW" ) @@ -27,6 +31,7 @@ var ( BLOCKTIMESTAMP: fnBlockTimestamp, NOW: fnBlockTimestamp, BLOCKCOINBASE: fnBlockCoinBase, + BLOCKGASLIMIT: fnBlockGasLimit, } ) @@ -110,3 +115,19 @@ func fnBlockCoinBase(ctx *common.Context, ops []*Operand, length uint64) (result return } +func fnBlockGasLimit(ctx *common.Context, ops []*Operand, length uint64) (result *Operand, err error) { + r := &Raw{} + if ctx.GasLimit > uint64(math.MaxInt64) { + r.Value, err = decimal.NewFromString(fmt.Sprint(ctx.GasLimit)) + if err != nil { + return + } + } else { + r.Value = decimal.New(int64(ctx.GasLimit), 0) + } + result = assignFuncResult( + []ast.DataType{ast.ComposeDataType(ast.DataTypeMajorUint, 7)}, + r.clone, length, + ) + return +} diff --git a/core/vm/sqlvm/runtime/functions_test.go b/core/vm/sqlvm/runtime/functions_test.go index cda24fcdf..638d8e2ec 100644 --- a/core/vm/sqlvm/runtime/functions_test.go +++ b/core/vm/sqlvm/runtime/functions_test.go @@ -1,6 +1,7 @@ package runtime import ( + "math" "math/big" "testing" @@ -11,6 +12,7 @@ import ( "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/core/vm/sqlvm/ast" "github.com/dexon-foundation/dexon/core/vm/sqlvm/common" + dec "github.com/dexon-foundation/dexon/core/vm/sqlvm/common/decimal" ) func TestFunction(t *testing.T) { @@ -258,3 +260,48 @@ func (s *FunctionSuite) TestFnCoinBase() { } } +func (s *FunctionSuite) TestFnGasLimit() { + type blockGasLimitCase struct { + Name string + Limit uint64 + Length uint64 + Res decimal.Decimal + Err error + } + testcases := []blockGasLimitCase{ + {"max int64 with length 1", uint64(math.MaxInt64), 1, dec.MaxInt64, nil}, + {"max uint64 with length 1", math.MaxUint64, 10, dec.MaxUint64, nil}, + {"address with length 0", math.MaxUint64, 0, decimal.Zero, nil}, + } + + callFn := func(c blockGasLimitCase) (*Operand, error) { + return fnBlockGasLimit( + &common.Context{ + Context: vm.Context{GasLimit: c.Limit}, + }, + nil, + c.Length) + } + + meta := []ast.DataType{ast.ComposeDataType(ast.DataTypeMajorUint, 7)} + + for idx, tCase := range testcases { + r, err := callFn(tCase) + s.Require().Equal( + tCase.Err, err, + "Index: %v. Error not expected: %v != %v", idx, tCase.Err, err) + s.Require().Equal( + meta, r.Meta, + "Index: %v. Meta not equal: %v != %v", idx, meta, r.Meta) + s.Require().Equal( + uint64(len(r.Data)), tCase.Length, + "Index: %v. Length not equal: %v != %v", idx, len(r.Data), tCase.Length) + + for i := 0; i < len(r.Data); i++ { + s.Require().True( + tCase.Res.Equal(r.Data[i][0].Value), + "Index: %v. Data Index: %v. Value not equal: %v != %v", + idx, i, tCase.Res, r.Data[i][0].Value) + } + } +} -- cgit v1.2.3