From ba915a703cda5172b37d20d93cc46c8d4c1ddc34 Mon Sep 17 00:00:00 2001 From: Meng-Ying Yang Date: Mon, 15 Apr 2019 12:01:34 +0800 Subject: core: vm: sqlvm: add built-in function BLOCK_COINBASE() --- core/vm/sqlvm/runtime/functions.go | 11 +++++++ core/vm/sqlvm/runtime/functions_test.go | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) (limited to 'core') diff --git a/core/vm/sqlvm/runtime/functions.go b/core/vm/sqlvm/runtime/functions.go index 90b1a93fe..c21d1da19 100644 --- a/core/vm/sqlvm/runtime/functions.go +++ b/core/vm/sqlvm/runtime/functions.go @@ -14,6 +14,7 @@ const ( BLOCKHASH = "BLOCK_HASH" BLOCKNUMBER = "BLOCK_NUMBER" BLOCKTIMESTAMP = "BLOCK_TIMESTAMP" + BLOCKCOINBASE = "BLOCK_COINBASE" NOW = "NOW" ) @@ -25,6 +26,7 @@ var ( BLOCKNUMBER: fnBlockNumber, BLOCKTIMESTAMP: fnBlockTimestamp, NOW: fnBlockTimestamp, + BLOCKCOINBASE: fnBlockCoinBase, } ) @@ -99,3 +101,12 @@ func fnBlockTimestamp(ctx *common.Context, ops []*Operand, length uint64) (resul return } +func fnBlockCoinBase(ctx *common.Context, ops []*Operand, length uint64) (result *Operand, err error) { + r := &Raw{Bytes: ctx.Coinbase.Bytes()} + result = assignFuncResult( + []ast.DataType{ast.ComposeDataType(ast.DataTypeMajorAddress, 0)}, + r.clone, length, + ) + return +} + diff --git a/core/vm/sqlvm/runtime/functions_test.go b/core/vm/sqlvm/runtime/functions_test.go index e90e9b6c6..cda24fcdf 100644 --- a/core/vm/sqlvm/runtime/functions_test.go +++ b/core/vm/sqlvm/runtime/functions_test.go @@ -205,3 +205,56 @@ func (s *FunctionSuite) TestFnBlockTimestamp() { } } +func (s *FunctionSuite) TestFnCoinBase() { + type blockCoinBaseCase struct { + Name string + Address dexCommon.Address + Length uint64 + Res []byte + Err error + } + + res := []byte{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x23, 0x45, 0x67} + address := dexCommon.BytesToAddress(res) + + testcases := []blockCoinBaseCase{ + {"address with length 1", address, 1, res, nil}, + {"address with length 10", address, 10, res, nil}, + {"address with length 0", address, 0, res, nil}, + } + + callFn := func(c blockCoinBaseCase) (*Operand, error) { + return fnBlockCoinBase( + &common.Context{ + Context: vm.Context{Coinbase: c.Address}, + }, + nil, + c.Length) + } + + meta := []ast.DataType{ast.ComposeDataType(ast.DataTypeMajorAddress, 0)} + + 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().Equal( + tCase.Res, r.Data[i][0].Bytes, + "Index: %v. Data Index: %v. Value not equal: %v != %v", + idx, i, tCase.Res, r.Data[i][0].Bytes) + } + } +} + -- cgit v1.2.3