github.com/aergoio/aergo@v1.3.1/contract/vm_test.go (about)

     1  package contract
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"math/big"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/aergoio/aergo/types"
    14  )
    15  
    16  const (
    17  	helloCode = `function hello(say) return "Hello " .. say end abi.register(hello)`
    18  
    19  	systemCode = `function testState()
    20  		system.setItem("key1", 999)
    21  		return system.getSender(), system.getTxhash(),system.getContractID(), system.getTimestamp(), system.getBlockheight(), system.getItem("key1")
    22  	  end 
    23  abi.register(testState)`
    24  
    25  	queryCode = `function inc()
    26  		a = system.getItem("key1")
    27  		if (a == nil) then
    28  			system.setItem("key1", 1)
    29  			return
    30  		end
    31  		system.setItem("key1", a + 1)
    32  	end
    33  	function query(a)
    34  			return system.getItem(a)
    35  	end
    36  	abi.register(query)
    37  	abi.payable(inc)`
    38  )
    39  
    40  func TestReturn(t *testing.T) {
    41  	bc, err := LoadDummyChain()
    42  	if err != nil {
    43  		t.Errorf("failed to create test database: %v", err)
    44  	}
    45  	defer bc.Release()
    46  
    47  	err = bc.ConnectBlock(
    48  		NewLuaTxAccount("ktlee", 100),
    49  		NewLuaTxDef("ktlee", "return_num", 0, "function return_num() return 10 end abi.register(return_num)"),
    50  		NewLuaTxCall("ktlee", "return_num", 0, `{"Name":"return_num", "Args":[]}`),
    51  	)
    52  	if err != nil {
    53  		t.Error(err)
    54  	}
    55  
    56  	err = bc.Query("return_num", `{"Name":"return_num", "Args":[]}`, "", "10")
    57  	if err != nil {
    58  		t.Error(err)
    59  	}
    60  
    61  	foo := `function foo()
    62  	return {1,2,3}
    63  end
    64  function foo2(bar)
    65  	return bar
    66  	end
    67  abi.register(foo,foo2)`
    68  
    69  	err = bc.ConnectBlock(
    70  		NewLuaTxDef("ktlee", "foo", 0, foo),
    71  	)
    72  	if err != nil {
    73  		t.Error(err)
    74  	}
    75  
    76  	err = bc.Query("foo", `{"Name":"foo", "Args":[]}`, "", "[1,2,3]")
    77  	if err != nil {
    78  		t.Error(err)
    79  	}
    80  	err = bc.Query("foo", `{"Name":"foo2", "Args":["foo314"]}`, "", `"foo314"`)
    81  	if err != nil {
    82  		t.Error(err)
    83  	}
    84  }
    85  
    86  func TestContractHello(t *testing.T) {
    87  	bc, err := LoadDummyChain()
    88  	if err != nil {
    89  		t.Errorf("failed to create test database: %v", err)
    90  	}
    91  	defer bc.Release()
    92  
    93  	_ = bc.ConnectBlock(
    94  		NewLuaTxAccount("ktlee", 100),
    95  	)
    96  	_ = bc.ConnectBlock(
    97  		NewLuaTxDef("ktlee", "hello", 0, helloCode),
    98  	)
    99  	tx := NewLuaTxCall("ktlee", "hello", 0, `{"Name":"hello", "Args":["World"]}`)
   100  	_ = bc.ConnectBlock(tx)
   101  	receipt := bc.getReceipt(tx.hash())
   102  	if receipt.GetRet() != `"Hello World"` {
   103  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
   104  	}
   105  }
   106  
   107  func TestContractSystem(t *testing.T) {
   108  	bc, err := LoadDummyChain()
   109  	if err != nil {
   110  		t.Errorf("failed to create test database: %v", err)
   111  	}
   112  	defer bc.Release()
   113  
   114  	_ = bc.ConnectBlock(
   115  		NewLuaTxAccount("ktlee", 100),
   116  	)
   117  	_ = bc.ConnectBlock(
   118  		NewLuaTxDef("ktlee", "system", 0, systemCode),
   119  	)
   120  	tx := NewLuaTxCall("ktlee", "system", 0, `{"Name":"testState", "Args":[]}`)
   121  	_ = bc.ConnectBlock(tx)
   122  	receipt := bc.getReceipt(tx.hash())
   123  	exRv := fmt.Sprintf(`["Amg6nZWXKB6YpNgBPv9atcjdm6hnFvs5wMdRgb2e9DmaF5g9muF2","99NTyZ796bpvwLLhMmsfwo8J3Wu3rUioUQsHE9CSYQKz","AmhNNBNY7XFk4p5ym4CJf8nTcRTEHjWzAeXJfhP71244CjBCAQU3",%d,3,999]`, bc.cBlock.Header.Timestamp/1e9)
   124  	if receipt.GetRet() != exRv {
   125  		t.Errorf("expected: %s, but got: %s", exRv, receipt.GetRet())
   126  	}
   127  }
   128  
   129  func TestGetABI(t *testing.T) {
   130  	bc, err := LoadDummyChain()
   131  	if err != nil {
   132  		t.Errorf("failed to create test database: %v", err)
   133  	}
   134  	defer bc.Release()
   135  
   136  	_ = bc.ConnectBlock(
   137  		NewLuaTxAccount("ktlee", 100),
   138  		NewLuaTxDef("ktlee", "hello", 0,
   139  			`state.var {
   140  	Say = state.value()
   141  }
   142  
   143  function hello(say) 
   144    return "Hello " .. say 
   145  end 
   146  
   147  abi.register(hello)`),
   148  	)
   149  	abi, err := bc.GetABI("hello")
   150  	if err != nil {
   151  		t.Error(err)
   152  	}
   153  	b, err := json.Marshal(abi)
   154  	if err != nil {
   155  		t.Error(err)
   156  	}
   157  	if string(b) != `{"version":"0.2","language":"lua","functions":[{"name":"hello","arguments":[{"name":"say"}]}],"state_variables":[{"name":"Say","type":"value"}]}` {
   158  		t.Error(string(b))
   159  	}
   160  }
   161  
   162  func TestContractQuery(t *testing.T) {
   163  	bc, err := LoadDummyChain()
   164  	if err != nil {
   165  		t.Errorf("failed to create test database: %v", err)
   166  	}
   167  	defer bc.Release()
   168  
   169  	_ = bc.ConnectBlock(
   170  		NewLuaTxAccount("ktlee", 100),
   171  	)
   172  	_ = bc.ConnectBlock(
   173  		NewLuaTxDef("ktlee", "query", 0, queryCode),
   174  		NewLuaTxCall("ktlee", "query", 2, `{"Name":"inc", "Args":[]}`),
   175  	)
   176  
   177  	ktlee, err := bc.GetAccountState("ktlee")
   178  	if err != nil {
   179  		t.Error(err)
   180  	}
   181  	if ktlee.GetBalanceBigInt().Uint64() != uint64(98) {
   182  		t.Error(ktlee.Balance)
   183  	}
   184  	query, err := bc.GetAccountState("query")
   185  	if err != nil {
   186  		t.Error(err)
   187  	}
   188  	if query.GetBalanceBigInt().Uint64() != uint64(2) {
   189  		t.Error(query.Balance)
   190  	}
   191  
   192  	err = bc.Query("query", `{"Name":"inc", "Args":[]}`, "set not permitted in query", "")
   193  	if err != nil {
   194  		t.Error(err)
   195  	}
   196  
   197  	err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "1")
   198  	if err != nil {
   199  		t.Error(err)
   200  	}
   201  }
   202  
   203  func TestRollback(t *testing.T) {
   204  	bc, err := LoadDummyChain()
   205  	if err != nil {
   206  		t.Errorf("failed to create test database: %v", err)
   207  	}
   208  	defer bc.Release()
   209  
   210  	_ = bc.ConnectBlock(
   211  		NewLuaTxAccount("ktlee", 100),
   212  	)
   213  	_ = bc.ConnectBlock(
   214  		NewLuaTxDef("ktlee", "query", 0, queryCode),
   215  		NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`),
   216  	)
   217  	_ = bc.ConnectBlock(
   218  		NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`),
   219  		NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`),
   220  	)
   221  	_ = bc.ConnectBlock(
   222  		NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`),
   223  		NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`),
   224  	)
   225  
   226  	err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "5")
   227  	if err != nil {
   228  		t.Error(err)
   229  	}
   230  
   231  	err = bc.DisConnectBlock()
   232  	if err != nil {
   233  		t.Error(err)
   234  	}
   235  	err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "3")
   236  	if err != nil {
   237  		t.Error(err)
   238  	}
   239  
   240  	err = bc.DisConnectBlock()
   241  	if err != nil {
   242  		t.Error(err)
   243  	}
   244  
   245  	err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "1")
   246  	if err != nil {
   247  		t.Error(err)
   248  	}
   249  
   250  	_ = bc.ConnectBlock(
   251  		NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`),
   252  	)
   253  
   254  	err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "2")
   255  	if err != nil {
   256  		t.Error(err)
   257  	}
   258  }
   259  
   260  func TestVote(t *testing.T) {
   261  	bc, err := LoadDummyChain()
   262  	if err != nil {
   263  		t.Errorf("failed to create test database: %v", err)
   264  	}
   265  	defer bc.Release()
   266  
   267  	definition := `
   268  function constructor()
   269  	system.setItem("owner", system.getSender())
   270  end
   271  
   272  function addCandidate(name)
   273  	if system.getSender() ~= system.getItem("owner") then
   274  		return
   275  	end
   276  
   277  	if (system.getItem(name) ~= nil) then
   278  		return
   279  	end
   280  	
   281  	local numCandidates;
   282  	if (system.getItem("numCandidates") == nil) then
   283  		numCandidates = 0;
   284  	else
   285  		numCandidates = tonumber(system.getItem("numCandidates"))
   286  	end
   287  
   288  	system.setItem("candidate_list_" .. numCandidates, name)
   289  
   290  	numCandidates = numCandidates + 1;
   291  	system.setItem("numCandidates", tostring(numCandidates));
   292  	system.setItem(name, tostring(0));
   293  end
   294  
   295  function getCandidates()
   296  	local numCandidates;
   297  	if (system.getItem("numCandidates") == nil) then
   298  		return {};
   299  	else
   300  		numCandidates = tonumber(system.getItem("numCandidates"))
   301  	end
   302  
   303  	local candidates = {};
   304  	local i = 0;
   305  
   306  	while true do
   307  		if (numCandidates == i) then
   308  			break;
   309  		end
   310  		local candidate = system.getItem("candidate_list_" .. i)
   311  		local count = system.getItem(candidate)
   312  		if count == nil then
   313  			count = 0
   314  		end
   315  		table.insert(candidates, {id = i, name = candidate, count = count});
   316  		i = i + 1;
   317  	end
   318  	return candidates;
   319  end
   320  
   321  function registerVoter(address)
   322  	if system.getSender() ~= system.getItem("owner") then
   323  		return
   324  	end
   325  	
   326  	system.setItem("voter_" .. address, "0");
   327  end
   328  
   329  function vote(candidateID)
   330  	local totalVoted
   331  	local voter = system.getItem("voter_" .. system.getSender())
   332  	if voter == nil then
   333  		return
   334  	end
   335  	totalVoted = tonumber(system.getItem("voter_" .. system.getSender()))
   336  	if totalVoted > 3 then
   337  		return
   338  	end
   339  	if system.getItem(candidateID) == nil then
   340  		return
   341  	end
   342  	local currentVotes;
   343  	if (system.getItem(candidateID) == nil) then
   344  		currentVotes = 0;
   345  	else
   346  		currentVotes = tonumber(system.getItem(candidateID))
   347  	end
   348  	currentVotes = currentVotes + 1
   349  
   350  	system.setItem(candidateID, tostring(currentVotes))
   351  	totalVoted = totalVoted + 1
   352  	system.setItem("voter_" .. system.getSender(), tostring(totalVoted));
   353  end
   354  
   355  abi.register(addCandidate, getCandidates, registerVoter, vote)`
   356  
   357  	_ = bc.ConnectBlock(
   358  		NewLuaTxAccount("owner", 100),
   359  		NewLuaTxDef("owner", "vote", 0, definition),
   360  		NewLuaTxAccount("user1", 100),
   361  	)
   362  
   363  	err = bc.ConnectBlock(
   364  		NewLuaTxCall(
   365  			"owner",
   366  			"vote",
   367  			0,
   368  			`{"Name":"addCandidate", "Args":["candidate1"]}`,
   369  		),
   370  		NewLuaTxCall(
   371  			"owner",
   372  			"vote",
   373  			0,
   374  			`{"Name":"addCandidate", "Args":["candidate2"]}`,
   375  		),
   376  		NewLuaTxCall(
   377  			"owner",
   378  			"vote",
   379  			0,
   380  			`{"Name":"addCandidate", "Args":["candidate3"]}`,
   381  		),
   382  	)
   383  	if err != nil {
   384  		t.Error(err)
   385  	}
   386  
   387  	err = bc.Query(
   388  		"vote",
   389  		`{"Name":"getCandidates"}`,
   390  		"",
   391  		`[{"count":"0","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`,
   392  	)
   393  	if err != nil {
   394  		t.Error(err)
   395  	}
   396  
   397  	_ = bc.ConnectBlock(
   398  		NewLuaTxCall(
   399  			"user1",
   400  			"vote",
   401  			0,
   402  			`{"Name":"addCandidate", "Args":["candidate4"]}`,
   403  		),
   404  	)
   405  	err = bc.Query(
   406  		"vote",
   407  		`{"Name":"getCandidates"}`,
   408  		"",
   409  		`[{"count":"0","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`,
   410  	)
   411  	if err != nil {
   412  		t.Error(err)
   413  	}
   414  
   415  	_ = bc.ConnectBlock(
   416  		// register voter
   417  		NewLuaTxCall(
   418  			"owner",
   419  			"vote",
   420  			0,
   421  			fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user10"))),
   422  		),
   423  		NewLuaTxCall(
   424  			"owner",
   425  			"vote",
   426  			0,
   427  			fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user10"))),
   428  		),
   429  		NewLuaTxCall(
   430  			"owner",
   431  			"vote",
   432  			0,
   433  			fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user11"))),
   434  		),
   435  		NewLuaTxCall(
   436  			"owner",
   437  			"vote",
   438  			0,
   439  			fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user1"))),
   440  		),
   441  		// vote
   442  		NewLuaTxCall(
   443  			"user1",
   444  			"vote",
   445  			0,
   446  			`{"Name":"vote", "Args":["user1"]}`,
   447  		),
   448  		NewLuaTxCall(
   449  			"user1",
   450  			"vote",
   451  			0,
   452  			`{"Name":"vote", "Args":["user1"]}`,
   453  		),
   454  		NewLuaTxCall(
   455  			"user1",
   456  			"vote",
   457  			0,
   458  			`{"Name":"vote", "Args":["user2"]}`,
   459  		),
   460  		NewLuaTxCall(
   461  			"user1",
   462  			"vote",
   463  			0,
   464  			`{"Name":"vote", "Args":["user2"]}`,
   465  		),
   466  		NewLuaTxCall(
   467  			"user1",
   468  			"vote",
   469  			0,
   470  			`{"Name":"vote", "Args":["user3"]}`,
   471  		),
   472  	)
   473  
   474  	err = bc.Query(
   475  		"vote",
   476  		`{"Name":"getCandidates"}`,
   477  		"",
   478  		`[{"count":"0","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`,
   479  	)
   480  	if err != nil {
   481  		t.Error(err)
   482  	}
   483  
   484  	_ = bc.ConnectBlock(
   485  		NewLuaTxCall(
   486  			"user11",
   487  			"vote",
   488  			0,
   489  			`{"Name":"vote", "Args":["candidate1"]}`,
   490  		),
   491  		NewLuaTxCall(
   492  			"user10",
   493  			"vote",
   494  			0,
   495  			`{"Name":"vote", "Args":["candidate1"]}`,
   496  		),
   497  	)
   498  
   499  	err = bc.Query(
   500  		"vote",
   501  		`{"Name":"getCandidates"}`,
   502  		"",
   503  		`[{"count":"2","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`,
   504  	)
   505  	if err != nil {
   506  		t.Error(err)
   507  	}
   508  }
   509  
   510  func TestInfiniteLoop(t *testing.T) {
   511  	bc, err := LoadDummyChain()
   512  	if err != nil {
   513  		t.Errorf("failed to create test database: %v", err)
   514  	}
   515  	defer bc.Release()
   516  
   517  	definition := `
   518  function infiniteLoop()
   519      local t = 0
   520  	while true do
   521  	    t = t + 1
   522  	end
   523  	return t
   524  end
   525  function infiniteCall()
   526  	infiniteCall()
   527  end
   528  function catch()
   529  	return pcall(infiniteLoop)
   530  end
   531  abi.register(infiniteLoop, infiniteCall, catch)`
   532  
   533  	err = bc.ConnectBlock(
   534  		NewLuaTxAccount("ktlee", 100),
   535  		NewLuaTxDef("ktlee", "loop", 0, definition),
   536  	)
   537  	if err != nil {
   538  		t.Error(err)
   539  	}
   540  
   541  	err = bc.ConnectBlock(
   542  		NewLuaTxCall(
   543  			"ktlee",
   544  			"loop",
   545  			0,
   546  			`{"Name":"infiniteLoop"}`,
   547  		),
   548  	)
   549  	errMsg := "exceeded the maximum instruction count"
   550  	if err == nil {
   551  		t.Errorf("expected: %s", errMsg)
   552  	}
   553  	if err != nil && !strings.Contains(err.Error(), errMsg) {
   554  		t.Error(err)
   555  	}
   556  
   557  	err = bc.ConnectBlock(
   558  		NewLuaTxCall(
   559  			"ktlee",
   560  			"loop",
   561  			0,
   562  			`{"Name":"catch"}`,
   563  		),
   564  	)
   565  	if err == nil {
   566  		t.Errorf("expected: %s", errMsg)
   567  	}
   568  	if err != nil && !strings.Contains(err.Error(), errMsg) {
   569  		t.Error(err)
   570  	}
   571  
   572  	err = bc.ConnectBlock(
   573  		NewLuaTxCall(
   574  			"ktlee",
   575  			"loop",
   576  			0,
   577  			`{"Name":"infiniteCall"}`,
   578  		),
   579  	)
   580  	errMsg = "stack overflow"
   581  	if err == nil {
   582  		t.Errorf("expected: %s", errMsg)
   583  	}
   584  	if err != nil && !strings.Contains(err.Error(), errMsg) {
   585  		t.Error(err)
   586  	}
   587  
   588  }
   589  
   590  func TestUpdateSize(t *testing.T) {
   591  	bc, err := LoadDummyChain()
   592  	if err != nil {
   593  		t.Errorf("failed to create test database: %v", err)
   594  	}
   595  	defer bc.Release()
   596  
   597  	definition := `
   598  function infiniteLoop()
   599  	for i = 1, 100000000000000 do
   600  		system.setItem("key_"..i, "value_"..i)
   601  	end
   602  end
   603  abi.register(infiniteLoop)`
   604  
   605  	err = bc.ConnectBlock(
   606  		NewLuaTxAccount("ktlee", 100),
   607  		NewLuaTxDef("ktlee", "loop", 0, definition),
   608  		NewLuaTxCall(
   609  			"ktlee",
   610  			"loop",
   611  			0,
   612  			`{"Name":"infiniteLoop"}`,
   613  		),
   614  	)
   615  	errMsg := "exceeded size of updates in the state database"
   616  	if err == nil {
   617  		t.Errorf("expected: %s", errMsg)
   618  	}
   619  	if err != nil && !strings.Contains(err.Error(), errMsg) {
   620  		t.Error(err)
   621  	}
   622  }
   623  
   624  func TestSqlVmSimple(t *testing.T) {
   625  	bc, err := LoadDummyChain()
   626  	if err != nil {
   627  		t.Errorf("failed to create test database: %v", err)
   628  	}
   629  	defer bc.Release()
   630  
   631  	definition := `
   632  function createAndInsert()
   633      db.exec("create table if not exists dual(dummy char(1))")
   634  	db.exec("insert into dual values ('X')")
   635      local insertYZ = db.prepare("insert into dual values (?),(?)")
   636      insertYZ:exec("Y", "Z")
   637  end
   638  
   639  function insertRollbackData()
   640  	db.exec("insert into dual values ('A'),('B'),('C')")
   641  end
   642  
   643  function query()
   644      local rt = {}
   645      local stmt = db.prepare("select ?+1, round(?, 1), dummy || ? as col3 from dual order by col3")
   646      local rs = stmt:query(1, 3.14, " Hello Blockchain")
   647      while rs:next() do
   648          local col1, col2, col3 = rs:get()
   649          table.insert(rt, col1)
   650          table.insert(rt, col2)
   651          table.insert(rt, col3)
   652      end
   653      return rt
   654  end
   655  
   656  function count()
   657  	local rs = db.query("select count(*) from dual")
   658  	if rs:next() then
   659  		local n = rs:get()
   660  		--rs:next()
   661  		return n
   662  	else
   663  		return "error in count()"
   664  	end
   665  end
   666  
   667  function all()
   668      local rt = {}
   669      local rs = db.query("select dummy from dual order by 1")
   670      while rs:next() do
   671          local col = rs:get()
   672          table.insert(rt, col)
   673      end
   674      return rt
   675  end
   676  
   677  abi.register(createAndInsert, insertRollbackData, query, count, all)`
   678  
   679  	_ = bc.ConnectBlock(
   680  		NewLuaTxAccount("ktlee", 100),
   681  		NewLuaTxDef("ktlee", "simple-query", 0, definition),
   682  	)
   683  	_ = bc.ConnectBlock(
   684  		NewLuaTxCall("ktlee", "simple-query", 0, `{"Name": "createAndInsert", "Args":[]}`),
   685  	)
   686  	err = bc.Query(
   687  		"simple-query",
   688  		`{"Name": "query", "Args":[]}`,
   689  		"",
   690  		`[2,3.1,"X Hello Blockchain",2,3.1,"Y Hello Blockchain",2,3.1,"Z Hello Blockchain"]`,
   691  	)
   692  	if err != nil {
   693  		t.Error(err)
   694  	}
   695  	err = bc.Query(
   696  		"simple-query",
   697  		`{"Name": "count", "Args":[]}`,
   698  		"",
   699  		`3`,
   700  	)
   701  	if err != nil {
   702  		t.Error(err)
   703  	}
   704  
   705  	_ = bc.ConnectBlock(
   706  		NewLuaTxCall("ktlee", "simple-query", 0, `{"Name": "createAndInsert", "Args":[]}`),
   707  	)
   708  	err = bc.Query(
   709  		"simple-query",
   710  		`{"Name": "count", "Args":[]}`,
   711  		"",
   712  		`6`,
   713  	)
   714  	if err != nil {
   715  		t.Error(err)
   716  	}
   717  
   718  	_ = bc.DisConnectBlock()
   719  
   720  	err = bc.Query(
   721  		"simple-query",
   722  		`{"Name": "count", "Args":[]}`,
   723  		"",
   724  		`3`,
   725  	)
   726  	if err != nil {
   727  		t.Error(err)
   728  	}
   729  
   730  	err = bc.DisConnectBlock()
   731  	if err != nil {
   732  		t.Error(err)
   733  	}
   734  	err = bc.DisConnectBlock()
   735  	if err != nil {
   736  		t.Error(err)
   737  	}
   738  
   739  	// there is only a genesis block
   740  	err = bc.Query(
   741  		"simple-query",
   742  		`{"Name": "count", "Args":[]}`,
   743  		"not found contract",
   744  		"",
   745  	)
   746  	if err != nil {
   747  		t.Error(err)
   748  	}
   749  }
   750  
   751  func TestSqlVmFail(t *testing.T) {
   752  	bc, err := LoadDummyChain()
   753  	if err != nil {
   754  		t.Errorf("failed to create test database: %v", err)
   755  	}
   756  	defer bc.Release()
   757  
   758  	definition := `
   759  function init()
   760      db.exec("create table if not exists total(n int)")
   761  	db.exec("insert into total values (0)")
   762  end
   763  
   764  function add(n)
   765  	local stmt = db.prepare("update total set n = n + ?")
   766  	stmt:exec(n)
   767  end
   768  
   769  function addFail(n)
   770  	local stmt = db.prepare("update set n = n + ?")
   771  	stmt:exec(n)
   772  end
   773  
   774  function get()
   775  	local rs = db.query("select n from total")
   776  	rs:next()
   777  	n = rs:get()
   778  	return n
   779  end
   780  abi.register(init, add, addFail, get)`
   781  
   782  	_ = bc.ConnectBlock(
   783  		NewLuaTxAccount("ktlee", 100),
   784  		NewLuaTxDef("ktlee", "fail", 0, definition),
   785  		NewLuaTxCall("ktlee", "fail", 0, `{"Name":"init"}`),
   786  	)
   787  
   788  	_ = bc.ConnectBlock(
   789  		NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[1]}`),
   790  	)
   791  
   792  	err = bc.ConnectBlock(
   793  		NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[2]}`),
   794  		NewLuaTxCall("ktlee", "fail", 0, `{"Name":"addFail", "Args":[3]}`).
   795  			Fail(`near "set": syntax error`),
   796  		NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[4]}`),
   797  	)
   798  	if err != nil {
   799  		t.Error(err)
   800  	}
   801  
   802  	_ = bc.ConnectBlock(
   803  		NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[5]}`),
   804  	)
   805  
   806  	err = bc.Query("fail", `{"Name":"get"}`, "", "12")
   807  	if err != nil {
   808  		t.Error(err)
   809  	}
   810  
   811  	_ = bc.DisConnectBlock()
   812  
   813  	err = bc.Query("fail", `{"Name":"get"}`, "", "7")
   814  	if err != nil {
   815  		t.Error(err)
   816  	}
   817  }
   818  
   819  func TestSqlVmDateTime(t *testing.T) {
   820  	bc, err := LoadDummyChain()
   821  	if err != nil {
   822  		t.Errorf("failed to create test database: %v", err)
   823  	}
   824  	defer bc.Release()
   825  
   826  	definition := `
   827  function init()
   828      db.exec("create table if not exists dt_test (n datetime, b bool)")
   829  	local n = db.exec("insert into dt_test values (?, ?),(date('2004-10-24', '+1 month', '-1 day'), 0)", 10000, 1)
   830  	assert(n == 2, "change count mismatch");
   831  end
   832  
   833  function nowNull()
   834  	db.exec("insert into dt_test values (date('now'), 0)")
   835  end
   836  
   837  function localtimeNull()
   838  	db.exec("insert into dt_test values (datetime('2018-05-25', ?), 1)", 'localtime')
   839  end
   840  
   841  function get()
   842  	local rs = db.query("select n, b from dt_test order by 1, 2")
   843  	local r = {}
   844  	while rs:next() do
   845  		local d, b = rs:get()
   846  		table.insert(r, { date= d, bool= b })
   847  	end
   848  	return r
   849  end
   850  abi.register(init, nowNull, localtimeNull, get)`
   851  
   852  	_ = bc.ConnectBlock(
   853  		NewLuaTxAccount("ktlee", 100),
   854  		NewLuaTxDef("ktlee", "datetime", 0, definition),
   855  		NewLuaTxCall("ktlee", "datetime", 0, `{"Name":"init"}`),
   856  	)
   857  
   858  	_ = bc.ConnectBlock(
   859  		NewLuaTxCall("ktlee", "datetime", 0, `{"Name":"nowNull"}`),
   860  	)
   861  
   862  	_ = bc.ConnectBlock(
   863  		NewLuaTxCall("ktlee", "datetime", 0, `{"Name":"localtimeNull"}`),
   864  	)
   865  
   866  	err = bc.Query(
   867  		"datetime",
   868  		`{"Name":"get"}`,
   869  		"",
   870  		`[{"bool":0},{"bool":1},{"bool":1,"date":"1970-01-01 02:46:40"},{"bool":0,"date":"2004-11-23"}]`,
   871  	)
   872  	if err != nil {
   873  		t.Error(err)
   874  	}
   875  }
   876  
   877  func TestSqlConstrains(t *testing.T) {
   878  	bc, err := LoadDummyChain()
   879  	if err != nil {
   880  		t.Errorf("failed to create test database: %v", err)
   881  	}
   882  	defer bc.Release()
   883  
   884  	definition := `
   885  function init()
   886      db.exec([[create table if not exists r (
   887    id integer primary key
   888  , n integer check(n >= 10)
   889  , nonull text not null
   890  , only integer unique)
   891  ]])
   892      db.exec("insert into r values (1, 11, 'text', 1)")
   893  	db.exec("create table if not exists s (rid integer references r(id))")
   894  end
   895  
   896  function pkFail()
   897  	db.exec("insert into r values (1, 12, 'text', 2)")
   898  end
   899  
   900  function checkFail()
   901  	db.exec("insert into r values (2, 9, 'text', 3)")
   902  end
   903  
   904  function fkFail()
   905  	db.exec("insert into s values (2)")
   906  end
   907  
   908  function notNullFail()
   909  	db.exec("insert into r values (2, 13, null, 2)")
   910  end
   911  
   912  function uniqueFail()
   913  	db.exec("insert into r values (2, 13, 'text', 1)")
   914  end
   915  
   916  abi.register(init, pkFail, checkFail, fkFail, notNullFail, uniqueFail)`
   917  
   918  	err = bc.ConnectBlock(
   919  		NewLuaTxAccount(
   920  			"ktlee",
   921  			100,
   922  		),
   923  		NewLuaTxDef(
   924  			"ktlee",
   925  			"constraint",
   926  			0,
   927  			definition,
   928  		),
   929  		NewLuaTxCall(
   930  			"ktlee",
   931  			"constraint",
   932  			0,
   933  			`{"Name":"init"}`,
   934  		),
   935  		NewLuaTxCall(
   936  			"ktlee",
   937  			"constraint",
   938  			0,
   939  			`{"Name":"pkFail"}`,
   940  		).Fail("UNIQUE constraint failed: r.id"),
   941  		NewLuaTxCall(
   942  			"ktlee",
   943  			"constraint",
   944  			0,
   945  			`{"Name":"checkFail"}`,
   946  		).Fail("CHECK constraint failed: r"),
   947  		NewLuaTxCall(
   948  			"ktlee",
   949  			"constraint",
   950  			0,
   951  			`{"Name":"fkFail"}`,
   952  		).Fail("FOREIGN KEY constraint failed"),
   953  		NewLuaTxCall(
   954  			"ktlee",
   955  			"constraint",
   956  			0,
   957  			`{"Name":"notNullFail"}`,
   958  		).Fail("NOT NULL constraint failed: r.nonull"),
   959  		NewLuaTxCall(
   960  			"ktlee",
   961  			"constraint",
   962  			0,
   963  			`{"Name":"uniqueFail"}`,
   964  		).Fail("UNIQUE constraint failed: r.only"),
   965  	)
   966  	if err != nil {
   967  		t.Error(err)
   968  	}
   969  }
   970  
   971  func TestSqlVmCustomer(t *testing.T) {
   972  	bc, err := LoadDummyChain()
   973  	if err != nil {
   974  		t.Errorf("failed to create test database: %v", err)
   975  	}
   976  	defer bc.Release()
   977  
   978  	definition := `
   979  function createTable()
   980    db.exec([[create table if not exists customer(
   981          id varchar(10),
   982          passwd varchar(20),
   983          name varchar(30),
   984          birth char(8),
   985          mobile varchar(20)
   986      )]])
   987  end
   988  
   989  function query(id)
   990      local rt = {}
   991      local rs = db.query("select * from customer where id like '%' || ? || '%'", id)
   992      while rs:next() do
   993          local col1, col2, col3, col4, col5 = rs:get()
   994          local item = {
   995                      id = col1,
   996                      passwd = col2,
   997                      name = col3,
   998                      birth = col4,
   999                      mobile = col5
  1000              }
  1001          table.insert(rt, item)
  1002      end
  1003      return rt
  1004  end
  1005  
  1006  function insert(id , passwd, name, birth, mobile)
  1007      local n = db.exec("insert into customer values (?,?,?,?,?)", id, passwd, name, birth, mobile)
  1008  	assert(n == 1, "insert count mismatch")
  1009  end
  1010  
  1011  function update(id , passwd)
  1012      local n = db.exec("update customer set passwd =? where id =?", passwd, id)
  1013  	assert(n == 1, "update count mismatch")
  1014  end
  1015  
  1016  function delete(id)
  1017      local n = db.exec("delete from customer where id =?", id)
  1018  	assert(n == 1, "delete count mismatch")
  1019  end
  1020  
  1021  function count()
  1022  	local rs = db.query("select count(*) from customer")
  1023  	if rs:next() then
  1024  		local n = rs:get()
  1025  		return n
  1026  	else
  1027  		return "error in count()"
  1028  	end
  1029  end
  1030  
  1031  abi.register(createTable, query, insert, update, delete, count)`
  1032  
  1033  	_ = bc.ConnectBlock(
  1034  		NewLuaTxAccount("ktlee", 100),
  1035  		NewLuaTxDef("ktlee", "customer", 0, definition),
  1036  		NewLuaTxCall(
  1037  			"ktlee",
  1038  			"customer",
  1039  			0,
  1040  			`{"Name":"createTable"}`,
  1041  		),
  1042  	)
  1043  
  1044  	_ = bc.ConnectBlock(
  1045  		NewLuaTxCall(
  1046  			"ktlee",
  1047  			"customer",
  1048  			0,
  1049  			`{"Name":"insert", "Args":["id1","passwd1","name1","20180524","010-1234-5678"]}`,
  1050  		),
  1051  	)
  1052  
  1053  	_ = bc.ConnectBlock(
  1054  		NewLuaTxCall(
  1055  			"ktlee",
  1056  			"customer",
  1057  			0,
  1058  			`{"Name":"insert", "Args":["id2","passwd2","name2","20180524","010-1234-5678"]}`,
  1059  		),
  1060  	)
  1061  
  1062  	_ = bc.ConnectBlock(
  1063  		NewLuaTxCall(
  1064  			"ktlee",
  1065  			"customer",
  1066  			0,
  1067  			`{"Name":"update", "Args":["id2","passwd3"]}`,
  1068  		),
  1069  	)
  1070  
  1071  	err = bc.Query("customer", `{"Name":"count"}`, "", "2")
  1072  	if err != nil {
  1073  		t.Error(err)
  1074  	}
  1075  
  1076  	_ = bc.DisConnectBlock()
  1077  
  1078  	err = bc.Query(
  1079  		"customer",
  1080  		`{"Name":"query", "Args":["id2"]}`,
  1081  		"",
  1082  		`[{"birth":"20180524","id":"id2","mobile":"010-1234-5678","name":"name2","passwd":"passwd2"}]`,
  1083  	)
  1084  	if err != nil {
  1085  		t.Error(err)
  1086  	}
  1087  
  1088  	_ = bc.ConnectBlock(
  1089  		NewLuaTxCall(
  1090  			"ktlee",
  1091  			"customer",
  1092  			0,
  1093  			`{"Name":"delete", "Args":["id2"]}`,
  1094  		),
  1095  	)
  1096  
  1097  	err = bc.Query(
  1098  		"customer",
  1099  		`{"Name":"query", "Args":["id2"]}`,
  1100  		"",
  1101  		`{}`,
  1102  	)
  1103  	if err != nil {
  1104  		t.Error(err)
  1105  	}
  1106  }
  1107  
  1108  func TestSqlVmDataType(t *testing.T) {
  1109  	bc, err := LoadDummyChain()
  1110  	if err != nil {
  1111  		t.Errorf("failed to create test database: %v", err)
  1112  	}
  1113  	defer bc.Release()
  1114  
  1115  	definition := `
  1116  function createDataTypeTable()
  1117    db.exec([[create table if not exists datatype_table(
  1118          var1 varchar(10),
  1119          char1 char(10),
  1120          int1 int(5),
  1121          float1 float(6),
  1122          blockheight1 long
  1123      )]])
  1124  end
  1125  
  1126  function dropDataTypeTable()
  1127     db.exec("drop table datatype_table")
  1128  end
  1129  
  1130  function insertDataTypeTable()
  1131      local stmt = db.prepare("insert into datatype_table values ('ABCD','fgh',1,3.14,?)")
  1132      stmt:exec(system.getBlockheight())
  1133  end
  1134  function queryOrderByDesc()
  1135      local rt = {}
  1136      local rs = db.query("select * from datatype_table order by blockheight1 desc")
  1137      while rs:next() do
  1138          local col1, col2, col3, col4, col5 = rs:get()
  1139          item = {
  1140                      var1 = col1,
  1141                      char1 = col2,
  1142                      int1 = col3,
  1143                      float1 = col4,
  1144                      blockheight1 = col5
  1145              }
  1146          table.insert(rt, item)
  1147      end
  1148      return rt
  1149  end
  1150  
  1151  function queryGroupByBlockheight1()
  1152      local rt = {}
  1153      local rs = db.query("select blockheight1, count(*), sum(int1), avg(float1) from datatype_table group by blockheight1")
  1154      while rs:next() do
  1155          local col1, col2, col3, col4 = rs:get()
  1156          item = {
  1157                      blockheight1 = col1,
  1158                      count1 = col2,
  1159                      sum_int1 = col3,
  1160                      avg_float1 =col4
  1161              }
  1162          table.insert(rt, item)
  1163      end
  1164      return rt
  1165  end
  1166  
  1167  abi.register(createDataTypeTable, dropDataTypeTable, insertDataTypeTable, queryOrderByDesc, queryGroupByBlockheight1)`
  1168  
  1169  	_ = bc.ConnectBlock(
  1170  		NewLuaTxAccount("ktlee", 100),
  1171  		NewLuaTxDef("ktlee", "datatype", 0, definition),
  1172  		NewLuaTxCall(
  1173  			"ktlee",
  1174  			"datatype",
  1175  			0,
  1176  			`{"Name":"createDataTypeTable"}`,
  1177  		),
  1178  	)
  1179  
  1180  	_ = bc.ConnectBlock(
  1181  		NewLuaTxCall(
  1182  			"ktlee",
  1183  			"datatype",
  1184  			0,
  1185  			`{"Name":"insertDataTypeTable"}`,
  1186  		),
  1187  		NewLuaTxCall(
  1188  			"ktlee",
  1189  			"datatype",
  1190  			0,
  1191  			`{"Name":"insertDataTypeTable"}`,
  1192  		),
  1193  		NewLuaTxCall(
  1194  			"ktlee",
  1195  			"datatype",
  1196  			0,
  1197  			`{"Name":"insertDataTypeTable"}`,
  1198  		),
  1199  	)
  1200  
  1201  	_ = bc.ConnectBlock(
  1202  		NewLuaTxCall(
  1203  			"ktlee",
  1204  			"datatype",
  1205  			0,
  1206  			`{"Name":"insertDataTypeTable"}`,
  1207  		),
  1208  	)
  1209  
  1210  	err = bc.Query(
  1211  		"datatype",
  1212  		`{"Name":"queryOrderByDesc"}`,
  1213  		"",
  1214  		`[{"blockheight1":3,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"},{"blockheight1":2,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"},{"blockheight1":2,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"},{"blockheight1":2,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"}]`,
  1215  	)
  1216  	if err != nil {
  1217  		t.Error(err)
  1218  	}
  1219  
  1220  	err = bc.Query(
  1221  		"datatype",
  1222  		`{"Name":"queryGroupByBlockheight1"}`,
  1223  		"",
  1224  		`[{"avg_float1":3.14,"blockheight1":2,"count1":3,"sum_int1":3},{"avg_float1":3.14,"blockheight1":3,"count1":1,"sum_int1":1}]`,
  1225  	)
  1226  	if err != nil {
  1227  		t.Error(err)
  1228  	}
  1229  }
  1230  
  1231  func TestSqlVmFunction(t *testing.T) {
  1232  	bc, err := LoadDummyChain()
  1233  	if err != nil {
  1234  		t.Errorf("failed to create test database: %v", err)
  1235  	}
  1236  	defer bc.Release()
  1237  
  1238  	definition := `
  1239  function sql_func()
  1240      local rt = {}
  1241      local rs = db.query("select round(3.14),min(1,2,3), max(4,5,6)")
  1242  	if rs:next() then
  1243  	    local col1, col2, col3 = rs:get()
  1244          table.insert(rt, col1)
  1245          table.insert(rt, col2)
  1246          table.insert(rt, col3)
  1247          return rt
  1248  	else
  1249  		return "error in func()"
  1250  	end
  1251  end
  1252  
  1253  function abs_func()
  1254      local rt = {}
  1255      local rs = db.query("select abs(-1),abs(0), abs(1)")
  1256  	if rs:next() then
  1257  	    local col1, col2, col3 = rs:get()
  1258          table.insert(rt, col1)
  1259          table.insert(rt, col2)
  1260          table.insert(rt, col3)
  1261          return rt
  1262  	else
  1263  		return "error in abs()"
  1264  	end
  1265  end
  1266  
  1267  function typeof_func()
  1268      local rt = {}
  1269      local rs = db.query("select typeof(-1), typeof('abc'), typeof(3.14), typeof(null)")
  1270  	if rs:next() then
  1271  	    local col1, col2, col3, col4 = rs:get()
  1272          table.insert(rt, col1)
  1273          table.insert(rt, col2)
  1274          table.insert(rt, col3)
  1275          table.insert(rt, col4)
  1276          return rt
  1277  	else
  1278  		return "error in typeof()"
  1279  	end
  1280  end
  1281  
  1282  abi.register(sql_func, abs_func, typeof_func)`
  1283  
  1284  	err = bc.ConnectBlock(
  1285  		NewLuaTxAccount("name", 100),
  1286  		NewLuaTxDef("ktlee", "fns", 0, definition),
  1287  	)
  1288  	if err != nil {
  1289  		t.Error(err)
  1290  	}
  1291  
  1292  	err = bc.Query("fns", `{"Name":"sql_func"}`, "", `[3,1,6]`)
  1293  	if err != nil {
  1294  		t.Error(err)
  1295  	}
  1296  
  1297  	err = bc.Query("fns", `{"Name":"abs_func"}`, "", `[1,0,1]`)
  1298  	if err != nil {
  1299  		t.Error(err)
  1300  	}
  1301  
  1302  	err = bc.Query("fns", `{"Name":"typeof_func"}`,
  1303  		"", `["integer","text","real","null"]`,
  1304  	)
  1305  	if err != nil {
  1306  		t.Error(err)
  1307  	}
  1308  }
  1309  
  1310  func TestSqlVmBook(t *testing.T) {
  1311  	bc, err := LoadDummyChain()
  1312  	if err != nil {
  1313  		t.Errorf("failed to create test database: %v", err)
  1314  	}
  1315  	defer bc.Release()
  1316  
  1317  	definition := `
  1318  function createTable()
  1319    db.exec([[create table if not exists book (
  1320          page number,
  1321          contents text
  1322      )]])
  1323  
  1324    db.exec([[create table if not exists copy_book (
  1325          page number,
  1326          contents text
  1327      )]])
  1328  end
  1329  
  1330  function makeBook()
  1331     	local stmt = db.prepare("insert into book values (?,?)")
  1332  	for i = 1, 100 do    
  1333     		stmt:exec(i, "value=" .. i*i)
  1334      end
  1335  end
  1336  
  1337  function copyBook()
  1338      local rs = db.query("select page, contents from book order by page asc")
  1339      while rs:next() do
  1340          local col1, col2 = rs:get()
  1341          local stmt_t = db.prepare("insert into copy_book values (?,?)")
  1342          stmt_t:exec(col1, col2)
  1343      end
  1344  end
  1345  
  1346  
  1347  function viewCopyBook()
  1348      local rt = {}
  1349      local rs = db.query("select max(page), min(contents) from copy_book")
  1350      while rs:next() do
  1351          local col1, col2 = rs:get()
  1352          table.insert(rt, col1)
  1353  		table.insert(rt, col2)
  1354      end
  1355      return rt
  1356  end
  1357  
  1358  function viewJoinBook()
  1359      local rt = {}
  1360      local rs = db.query([[select c.page, b.page, c.contents  
  1361  							from copy_book c, book b 
  1362  							where c.page = b.page and c.page = 10 ]])
  1363      while rs:next() do
  1364          local col1, col2, col3 = rs:get()
  1365          table.insert(rt, col1)
  1366  		table.insert(rt, col2)
  1367  		table.insert(rt, col3)
  1368      end
  1369      return rt
  1370  end
  1371  
  1372  abi.register(createTable, makeBook, copyBook, viewCopyBook, viewJoinBook)`
  1373  
  1374  	err = bc.ConnectBlock(
  1375  		NewLuaTxAccount("ktlee", 100),
  1376  		NewLuaTxDef("ktlee", "book", 0, definition),
  1377  		NewLuaTxCall(
  1378  			"ktlee",
  1379  			"book",
  1380  			0,
  1381  			`{"Name":"createTable"}`,
  1382  		),
  1383  	)
  1384  	if err != nil {
  1385  		t.Error(err)
  1386  	}
  1387  
  1388  	err = bc.ConnectBlock(
  1389  		NewLuaTxCall(
  1390  			"ktlee",
  1391  			"book",
  1392  			0,
  1393  			`{"Name":"makeBook"}`,
  1394  		),
  1395  	)
  1396  	if err != nil {
  1397  		t.Error(err)
  1398  	}
  1399  
  1400  	err = bc.ConnectBlock(
  1401  		NewLuaTxCall(
  1402  			"ktlee",
  1403  			"book",
  1404  			0,
  1405  			`{"Name":"copyBook"}`,
  1406  		),
  1407  	)
  1408  	if err != nil {
  1409  		t.Error(err)
  1410  	}
  1411  
  1412  	err = bc.Query(
  1413  		"book",
  1414  		`{"Name":"viewCopyBook"}`,
  1415  		"",
  1416  		`[100,"value=1"]`,
  1417  	)
  1418  	if err != nil {
  1419  		t.Error(err)
  1420  	}
  1421  }
  1422  
  1423  func TestSqlVmDateformat(t *testing.T) {
  1424  	bc, err := LoadDummyChain()
  1425  	if err != nil {
  1426  		t.Errorf("failed to create test database: %v", err)
  1427  	}
  1428  	defer bc.Release()
  1429  
  1430  	definition := `
  1431  function init()
  1432  	db.exec("drop table if exists dateformat_test")
  1433  	db.exec([[create table if not exists dateformat_test
  1434  	(
  1435  		col1 date ,
  1436  		col2 datetime ,
  1437  		col3 text
  1438  	)]])
  1439  	db.exec("insert into dateformat_test values (date('2004-10-24 11:11:11'), datetime('2004-10-24 11:11:11'),strftime('%Y%m%d%H%M%S','2004-10-24 11:11:11'))")
  1440  	db.exec("insert into dateformat_test values (date(1527504338,'unixepoch'), datetime(1527504338,'unixepoch'), strftime('%Y%m%d%H%M%S',1527504338,'unixepoch') )")
  1441  end
  1442  
  1443  function get()
  1444      local rt = {}
  1445      local rs = db.query([[select col1, col2, col3
  1446                              from dateformat_test ]])
  1447      while rs:next() do
  1448          local col1, col2, col3 = rs:get()
  1449          table.insert(rt, {col1,col2,col3} )
  1450      end
  1451      return rt
  1452  end
  1453  
  1454  abi.register(init, get)`
  1455  
  1456  	err = bc.ConnectBlock(
  1457  		NewLuaTxAccount("ktlee", 100),
  1458  		NewLuaTxDef(
  1459  			"ktlee",
  1460  			"data_format",
  1461  			0,
  1462  			definition,
  1463  		),
  1464  		NewLuaTxCall("ktlee", "data_format", 0, `{"Name":"init"}`),
  1465  	)
  1466  	if err != nil {
  1467  		t.Error(err)
  1468  	}
  1469  
  1470  	err = bc.Query(
  1471  		"data_format",
  1472  		`{"Name":"get"}`,
  1473  		"",
  1474  		`[["2004-10-24","2004-10-24 11:11:11","20041024111111"],["2018-05-28","2018-05-28 10:45:38","20180528104538"]]`,
  1475  	)
  1476  	if err != nil {
  1477  		t.Error(err)
  1478  	}
  1479  }
  1480  
  1481  func TestSqlVmRecursiveData(t *testing.T) {
  1482  	bc, err := LoadDummyChain()
  1483  	if err != nil {
  1484  		t.Errorf("failed to create test database: %v", err)
  1485  	}
  1486  	defer bc.Release()
  1487  
  1488  	definition := `
  1489  function r()
  1490  	local t = {}
  1491  	t["name"] = "ktlee"
  1492  	t["self"] = t
  1493  	return t
  1494  end
  1495  abi.register(r)`
  1496  
  1497  	tx := NewLuaTxCall("ktlee", "r", 0, `{"Name":"r"}`)
  1498  	err = bc.ConnectBlock(
  1499  		NewLuaTxAccount("ktlee", 100),
  1500  		NewLuaTxDef("ktlee", "r", 0, definition),
  1501  		tx,
  1502  	)
  1503  	if err == nil {
  1504  		t.Error(err)
  1505  	}
  1506  	if err.Error() != `nested table error` {
  1507  		t.Errorf("contract Call ret error :%s", err.Error())
  1508  	}
  1509  }
  1510  
  1511  func TestContractCall(t *testing.T) {
  1512  	definition1 := `
  1513  	function constructor(init)
  1514  		system.setItem("count", init)
  1515  	end
  1516  	function inc()
  1517  		count = system.getItem("count")
  1518  		system.setItem("count", count + 1)
  1519  		return count
  1520  	end
  1521  
  1522  	function get()
  1523  		return system.getItem("count")
  1524  	end
  1525  
  1526  	function set(val)
  1527  		system.setItem("count", val)
  1528  	end
  1529  	abi.register(inc,get,set)
  1530  	`
  1531  
  1532  	bc, err := LoadDummyChain()
  1533  	if err != nil {
  1534  		t.Errorf("failed to create test database: %v", err)
  1535  	}
  1536  	defer bc.Release()
  1537  
  1538  	err = bc.ConnectBlock(
  1539  		NewLuaTxAccount("ktlee", 100),
  1540  		NewLuaTxDef("ktlee", "counter", 0, definition1).Constructor("[1]"),
  1541  		NewLuaTxCall("ktlee", "counter", 0, `{"Name":"inc", "Args":[]}`),
  1542  	)
  1543  	if err != nil {
  1544  		t.Error(err)
  1545  	}
  1546  
  1547  	err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "2")
  1548  	if err != nil {
  1549  		t.Error(err)
  1550  	}
  1551  
  1552  	definition2 := `
  1553  	function constructor(addr)
  1554  		system.setItem("count", 99)
  1555  		system.setItem("addr", addr)
  1556  	end
  1557  	function add(amount)
  1558  		return contract.call.value(amount)(system.getItem("addr"), "inc")
  1559  	end
  1560  	function dadd()
  1561  		return contract.delegatecall(system.getItem("addr"), "inc")
  1562  	end
  1563  	function get()
  1564  		addr = system.getItem("addr")
  1565  		a = contract.call(addr, "get")
  1566  		return a
  1567  	end
  1568  	function dget()
  1569  		addr = system.getItem("addr")
  1570  		a = contract.delegatecall(addr, "get")
  1571  		return a
  1572  	end
  1573  	function set(val)
  1574  		contract.call(system.getItem("addr"), "set", val)
  1575  	end
  1576  	function dset(val)
  1577  		contract.delegatecall(system.getItem("addr"), "set", val)
  1578  	end
  1579  	abi.register(add,dadd, get, dget, set, dset)
  1580  	`
  1581  	err = bc.ConnectBlock(
  1582  		NewLuaTxDef("ktlee", "caller", 0, definition2).
  1583  			Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("counter")))),
  1584  		NewLuaTxCall("ktlee", "caller", 0, `{"Name":"add", "Args":[]}`),
  1585  	)
  1586  	if err != nil {
  1587  		t.Error(err)
  1588  	}
  1589  	err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "3")
  1590  	if err != nil {
  1591  		t.Error(err)
  1592  	}
  1593  	err = bc.Query("caller", `{"Name":"dget", "Args":[]}`, "", "99")
  1594  	if err != nil {
  1595  		t.Error(err)
  1596  	}
  1597  	tx := NewLuaTxCall("ktlee", "caller", 0, `{"Name":"dadd", "Args":[]}`)
  1598  	_ = bc.ConnectBlock(tx)
  1599  	receipt := bc.getReceipt(tx.hash())
  1600  	if receipt.GetRet() != `99` {
  1601  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  1602  	}
  1603  	tx = NewLuaTxCall("ktlee", "caller", 0, `{"Name":"dadd", "Args":[]}`)
  1604  	_ = bc.ConnectBlock(tx)
  1605  	receipt = bc.getReceipt(tx.hash())
  1606  	if receipt.GetRet() != `100` {
  1607  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  1608  	}
  1609  	err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "3")
  1610  	if err != nil {
  1611  		t.Error(err)
  1612  	}
  1613  }
  1614  
  1615  func TestSparseTable(t *testing.T) {
  1616  	bc, err := LoadDummyChain()
  1617  	if err != nil {
  1618  		t.Errorf("failed to create test database: %v", err)
  1619  	}
  1620  	defer bc.Release()
  1621  
  1622  	definition := `
  1623  function is_table_equal(t1,t2,ignore_mt)
  1624     local ty1 = type(t1)
  1625     local ty2 = type(t2)
  1626     if ty1 ~= ty2 then return false end
  1627     -- non-table types can be directly compared
  1628     if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end
  1629     -- as well as tables which have the metamethod __eq
  1630     local mt = getmetatable(t1)
  1631     if not ignore_mt and mt and mt.__eq then return t1 == t2 end
  1632     for k1,v1 in pairs(t1) do
  1633        local v2 = t2[k1]
  1634        if v2 == nil or not is_table_equal(v1,v2) then return false end
  1635     end
  1636     for k2,v2 in pairs(t2) do
  1637        local v1 = t1[k2]
  1638        if v1 == nil or not is_table_equal(v1,v2) then return false end
  1639     end
  1640     return true
  1641  end
  1642  
  1643  function r()
  1644  	local t = {}
  1645  	t[10000] = "1234"
  1646  	system.setItem("k", t)
  1647  	k = system.getItem("k")
  1648  	if is_table_equal(t, k, false) then
  1649  		return 1
  1650      end
  1651  	return 0
  1652  end
  1653  abi.register(r)`
  1654  
  1655  	tx := NewLuaTxCall("ktlee", "r", 0, `{"Name":"r"}`)
  1656  	err = bc.ConnectBlock(
  1657  		NewLuaTxAccount("ktlee", 100),
  1658  		NewLuaTxDef("ktlee", "r", 0, definition),
  1659  		tx,
  1660  	)
  1661  	if err != nil {
  1662  		t.Error(err)
  1663  	}
  1664  	receipt := bc.getReceipt(tx.hash())
  1665  	if receipt.GetRet() != `1` {
  1666  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  1667  	}
  1668  }
  1669  
  1670  func TestKvstore(t *testing.T) {
  1671  	definition := `
  1672  	state.var{
  1673  		counts = state.map(),
  1674  		name = state.value()
  1675  	}
  1676  
  1677  	function inc(key)
  1678  		if counts[key] == nil then
  1679  			counts[key] = 0
  1680  		end
  1681  		counts[key] = counts[key] + 1
  1682  	end
  1683  
  1684  	function get(key)
  1685  		return counts[key]
  1686  	end
  1687  
  1688  	function set(key,val)
  1689  		counts[key] = val
  1690  	end
  1691  
  1692  	function setname(n)
  1693  		name:set(n)
  1694  	end
  1695  
  1696  	function getname()
  1697  		return name:get()
  1698  	end
  1699  
  1700  	abi.register(inc,get,set,setname,getname)`
  1701  
  1702  	bc, err := LoadDummyChain()
  1703  	if err != nil {
  1704  		t.Errorf("failed to create test database: %v", err)
  1705  	}
  1706  	defer bc.Release()
  1707  
  1708  	err = bc.ConnectBlock(
  1709  		NewLuaTxAccount("ktlee", 100),
  1710  		NewLuaTxDef("ktlee", "map", 0, definition),
  1711  	)
  1712  	if err != nil {
  1713  		t.Error(err)
  1714  	}
  1715  	err = bc.ConnectBlock(
  1716  		NewLuaTxCall("ktlee", "map", 0, `{"Name":"inc", "Args":["ktlee"]}`),
  1717  		NewLuaTxCall("ktlee", "map", 0, `{"Name":"setname", "Args":["eve2adam"]}`),
  1718  	)
  1719  	if err != nil {
  1720  		t.Error(err)
  1721  	}
  1722  	err = bc.ConnectBlock()
  1723  	if err != nil {
  1724  		t.Error(err)
  1725  	}
  1726  
  1727  	err = bc.Query("map", `{"Name":"get", "Args":["ktlee"]}`, "", "1")
  1728  	if err != nil {
  1729  		t.Error(err)
  1730  	}
  1731  	err = bc.Query("map", `{"Name":"get", "Args":["htwo"]}`, "", "{}")
  1732  	if err != nil {
  1733  		t.Error(err)
  1734  	}
  1735  
  1736  	err = bc.ConnectBlock(
  1737  		NewLuaTxCall("ktlee", "map", 0, `{"Name":"inc", "Args":["ktlee"]}`),
  1738  		NewLuaTxCall("ktlee", "map", 0, `{"Name":"inc", "Args":["htwo"]}`),
  1739  		NewLuaTxCall("ktlee", "map", 0, `{"Name":"set", "Args":["wook", 100]}`),
  1740  	)
  1741  	if err != nil {
  1742  		t.Error(err)
  1743  	}
  1744  
  1745  	err = bc.Query("map", `{"Name":"get", "Args":["ktlee"]}`, "", "2")
  1746  	if err != nil {
  1747  		t.Error(err)
  1748  	}
  1749  	err = bc.Query("map", `{"Name":"get", "Args":["htwo"]}`, "", "1")
  1750  	if err != nil {
  1751  		t.Error(err)
  1752  	}
  1753  	err = bc.Query("map", `{"Name":"get", "Args":["wook"]}`, "", "100")
  1754  	if err != nil {
  1755  		t.Error(err)
  1756  	}
  1757  	err = bc.Query("map", `{"Name":"getname"}`, "", `"eve2adam"`)
  1758  	if err != nil {
  1759  		t.Error(err)
  1760  	}
  1761  }
  1762  
  1763  func TestJson(t *testing.T) {
  1764  	definition := `
  1765  	state.var{
  1766  		table = state.value()
  1767  	}
  1768  
  1769  	function set(val)
  1770  		table:set(json.decode(val))
  1771  	end
  1772  
  1773  	function get()
  1774  		return table:get()
  1775  	end
  1776  
  1777  	function getenc()
  1778  		return json.encode(table:get())
  1779  	end
  1780  	
  1781  	function getlen()
  1782  		a = table:get()
  1783  		return a[1], string.len(a[1])
  1784  	end
  1785  
  1786  	function getAmount()
  1787  		return system.getAmount()
  1788  	end
  1789  
  1790  	abi.register(set, get, getenc, getlen)
  1791  	abi.payable(getAmount)`
  1792  
  1793  	bc, err := LoadDummyChain()
  1794  	if err != nil {
  1795  		t.Errorf("failed to create test database: %v", err)
  1796  	}
  1797  	defer bc.Release()
  1798  
  1799  	err = bc.ConnectBlock(
  1800  		NewLuaTxAccount("ktlee", 100),
  1801  		NewLuaTxDef("ktlee", "json", 0, definition),
  1802  	)
  1803  	if err != nil {
  1804  		t.Error(err)
  1805  	}
  1806  	err = bc.ConnectBlock(
  1807  		NewLuaTxCall("ktlee", "json", 0, `{"Name":"set", "Args":["[1,2,3]"]}`),
  1808  	)
  1809  	if err != nil {
  1810  		t.Error(err)
  1811  	}
  1812  	err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", "[1,2,3]")
  1813  	if err != nil {
  1814  		t.Error(err)
  1815  	}
  1816  	err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"[1,2,3]"`)
  1817  	if err != nil {
  1818  		t.Error(err)
  1819  	}
  1820  	err = bc.ConnectBlock(
  1821  		NewLuaTxCall("ktlee", "json", 0,
  1822  			`{"Name":"set", "Args":["{\"key1\":[1,2,3], \"run\", \"key2\":5, [4,5,6]}"]}`),
  1823  	)
  1824  	if err != nil {
  1825  		t.Error(err)
  1826  	}
  1827  	err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `{"1":"run","2":[4,5,6],"key1":[1,2,3],"key2":5}`)
  1828  	if err != nil {
  1829  		t.Error(err)
  1830  	}
  1831  	err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"{\"1\":\"run\",\"2\":[4,5,6],\"key1\":[1,2,3],\"key2\":5}"`)
  1832  	if err != nil {
  1833  		t.Error(err)
  1834  	}
  1835  	err = bc.ConnectBlock(
  1836  		NewLuaTxCall("ktlee", "json", 0,
  1837  			`{"Name":"set", "Args":["{\"key1\":{\"arg1\": 1,\"arg2\":{}, \"arg3\":[]}, \"key2\":[5,4,3]}"]}`),
  1838  	)
  1839  	if err != nil {
  1840  		t.Error(err)
  1841  	}
  1842  	err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `{"key1":{"arg1":1,"arg2":{},"arg3":{}},"key2":[5,4,3]}`)
  1843  	if err != nil {
  1844  		t.Error(err)
  1845  	}
  1846  	err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"{\"key1\":{\"arg1\":1,\"arg2\":{},\"arg3\":{}},\"key2\":[5,4,3]}"`)
  1847  	if err != nil {
  1848  		t.Error(err)
  1849  	}
  1850  	err = bc.ConnectBlock(
  1851  		NewLuaTxCall("ktlee", "json", 0,
  1852  			`{"Name":"set", "Args":["{\"key1\":[1,2,3], \"key1\":5}"]}`),
  1853  	)
  1854  	if err != nil {
  1855  		t.Error(err)
  1856  	}
  1857  	err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `{"key1":5}`)
  1858  	if err != nil {
  1859  		t.Error(err)
  1860  	}
  1861  	err = bc.ConnectBlock(
  1862  		NewLuaTxCall("ktlee", "json", 0, `{"Name":"set", "Args":["[\"\\\"hh\\t\",\"2\",3]"]}`),
  1863  	)
  1864  	if err != nil {
  1865  		t.Error(err)
  1866  	}
  1867  	err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `["\"hh\u0009","2",3]`)
  1868  	if err != nil {
  1869  		t.Error(err)
  1870  	}
  1871  	err = bc.Query("json", `{"Name":"getlen", "Args":[]}`, "", `["\"hh\u0009",4]`)
  1872  	if err != nil {
  1873  		t.Error(err)
  1874  	}
  1875  	err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"[\"\\\"hh\\u0009\",\"2\",3]"`)
  1876  	if err != nil {
  1877  		t.Error(err)
  1878  	}
  1879  	tx := NewLuaTxCall("ktlee", "json", 100, `{"Name":"getAmount"}`)
  1880  	err = bc.ConnectBlock(tx)
  1881  	if err != nil {
  1882  		t.Error(err)
  1883  	}
  1884  	receipt := bc.getReceipt(tx.hash())
  1885  	if receipt.GetRet() != `"100"` {
  1886  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  1887  	}
  1888  	err = bc.ConnectBlock(
  1889  		NewLuaTxCall("ktlee", "json", 0,
  1890  			`{"Name":"set", "Args":["{\"key1\":[1,2,3], \"key1\":5}}"]}`).Fail("not proper json format"),
  1891  	)
  1892  }
  1893  
  1894  func TestArray(t *testing.T) {
  1895  	definition := `
  1896  	state.var{
  1897  		counts = state.array(10)
  1898  	}
  1899  
  1900  	function inc(key)
  1901  		if counts[key] == nil then
  1902  			counts[key] = 0
  1903  		end
  1904  		counts[key] = counts[key] + 1
  1905  	end
  1906  
  1907  	function get(key)
  1908  		return counts[key]
  1909  	end
  1910  
  1911  	function set(key,val)
  1912  		counts[key] = val
  1913  	end
  1914  
  1915  	function len()
  1916  		return counts:length()
  1917  	end
  1918  
  1919  	function iter()
  1920  		local rv = {}
  1921  		for i, v in counts:ipairs() do 
  1922  			if v == nil then
  1923  				rv[i] = "nil"
  1924  			else
  1925  				rv[i] = v
  1926  			end
  1927  		end
  1928  		return rv
  1929  	end
  1930  
  1931  	abi.register(inc,get,set,len,iter)`
  1932  
  1933  	bc, err := LoadDummyChain()
  1934  	if err != nil {
  1935  		t.Errorf("failed to create test database: %v", err)
  1936  	}
  1937  	defer bc.Release()
  1938  
  1939  	err = bc.ConnectBlock(
  1940  		NewLuaTxAccount("ktlee", 100),
  1941  		NewLuaTxDef("ktlee", "array", 0, definition),
  1942  	)
  1943  	if err != nil {
  1944  		t.Error(err)
  1945  	}
  1946  	err = bc.ConnectBlock(
  1947  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[1]}`),
  1948  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[0]}`).Fail("index out of range"),
  1949  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[1]}`),
  1950  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[1.00000001]}`).Fail("integer expected, got number"),
  1951  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":["1"]}`).Fail("integer expected, got string)"),
  1952  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[true]}`).Fail("integer expected, got boolean"),
  1953  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[[1, 2]]}`).Fail("integer expected, got table"),
  1954  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[null]}`).Fail("integer expected, got nil)"),
  1955  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[{}]}`).Fail("integer expected, got table)"),
  1956  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[""]}`).Fail("integer expected, got string)"),
  1957  		NewLuaTxCall("ktlee", "array", 0, `{"Name":"set", "Args":[2,"ktlee"]}`),
  1958  	)
  1959  	if err != nil {
  1960  		t.Error(err)
  1961  	}
  1962  	err = bc.Query("array", `{"Name":"get", "Args":[11]}`, "index out of range", "")
  1963  	if err != nil {
  1964  		t.Error(err)
  1965  	}
  1966  	err = bc.Query("array", `{"Name":"get", "Args":[1]}`, "", "2")
  1967  	if err != nil {
  1968  		t.Error(err)
  1969  	}
  1970  	err = bc.Query("array", `{"Name":"get", "Args":[2]}`, "", `"ktlee"`)
  1971  	if err != nil {
  1972  		t.Error(err)
  1973  	}
  1974  	err = bc.Query("array", `{"Name":"len"}`, "", `10`)
  1975  	if err != nil {
  1976  		t.Error(err)
  1977  	}
  1978  	err = bc.Query("array", `{"Name":"iter"}`, "", `[2,"ktlee","nil","nil","nil","nil","nil","nil","nil","nil"]`)
  1979  	if err != nil {
  1980  		t.Error(err)
  1981  	}
  1982  	overflow := `
  1983  	state.var{
  1984  		counts = state.array(1000000000000)
  1985  	}
  1986  
  1987  	function get()
  1988  		return "hello"
  1989  	end
  1990  	
  1991  	abi.register(get)
  1992  	`
  1993  	err = bc.ConnectBlock(
  1994  		NewLuaTxDef("ktlee", "overflow", 0, overflow),
  1995  	)
  1996  	errMsg := "integer expected, got number"
  1997  	if err == nil {
  1998  		t.Errorf("expected: '%s', but got: nil", errMsg)
  1999  	} else if !strings.Contains(err.Error(), errMsg) {
  2000  		t.Errorf("expected: %s, but got: %s", errMsg, err.Error())
  2001  	}
  2002  }
  2003  
  2004  func TestPcall(t *testing.T) {
  2005  	definition1 := `
  2006  	function constructor(init)
  2007  		system.setItem("count", init)
  2008  	end
  2009  
  2010  	function init()
  2011  		db.exec([[create table if not exists r (
  2012  	  id integer primary key
  2013  	, n integer check(n >= 10)
  2014  	, nonull text not null
  2015  	, only integer unique)
  2016  	]])
  2017  		db.exec("insert into r values (1, 11, 'text', 1)")
  2018  	end
  2019  
  2020  	function pkins1()
  2021  		db.exec("insert into r values (3, 12, 'text', 2)")
  2022  		db.exec("insert into r values (1, 12, 'text', 2)")
  2023  	end
  2024  
  2025  	function pkins2()
  2026  		db.exec("insert into r values (4, 12, 'text', 2)")
  2027  	end
  2028  
  2029  	function pkget()
  2030  		local rs = db.query("select count(*) from r")
  2031  		if rs:next() then
  2032  			local n = rs:get()
  2033  			--rs:next()
  2034  			return n
  2035  		else
  2036  			return "error in count()"
  2037  		end
  2038  	end
  2039  
  2040  	function inc()
  2041  		count = system.getItem("count")
  2042  		system.setItem("count", count + 1)
  2043  		return count
  2044  	end
  2045  
  2046  	function get()
  2047  		return system.getItem("count")
  2048  	end
  2049  
  2050  	function getOrigin()
  2051  		return system.getOrigin()
  2052  	end
  2053  
  2054  	function set(val)
  2055  		system.setItem("count", val)
  2056  	end
  2057  	abi.register(inc,get,set, init, pkins1, pkins2, pkget, getOrigin)
  2058  	abi.payable(constructor, inc)
  2059  	`
  2060  
  2061  	bc, err := LoadDummyChain()
  2062  	if err != nil {
  2063  		t.Errorf("failed to create test database: %v", err)
  2064  	}
  2065  	defer bc.Release()
  2066  
  2067  	err = bc.ConnectBlock(
  2068  		NewLuaTxAccount("ktlee", 100),
  2069  		NewLuaTxDef("ktlee", "counter", 10, definition1).Constructor("[0]"),
  2070  		NewLuaTxCall("ktlee", "counter", 15, `{"Name":"inc", "Args":[]}`),
  2071  	)
  2072  
  2073  	err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1")
  2074  	if err != nil {
  2075  		t.Error(err)
  2076  	}
  2077  
  2078  	definition2 := `
  2079  	function constructor(addr)
  2080  		system.setItem("count", 99)
  2081  		system.setItem("addr", addr)
  2082  	end
  2083  	function add(amount)
  2084  		first = contract.call.value(amount)(system.getItem("addr"), "inc")
  2085  		status, res = contract.pcall(contract.call.value(1000000), system.getItem("addr"), "inc")
  2086  		if status == false then
  2087  			return first
  2088  		end
  2089  		return res
  2090  	end
  2091  	function dadd()
  2092  		return contract.delegatecall(system.getItem("addr"), "inc")
  2093  	end
  2094  	function get()
  2095  		addr = system.getItem("addr")
  2096  		a = contract.call(addr, "get")
  2097  		return a
  2098  	end
  2099  	function dget()
  2100  		addr = system.getItem("addr")
  2101  		a = contract.delegatecall(addr, "get")
  2102  		return a
  2103  	end
  2104  	function send(addr, amount)
  2105  		contract.send(addr, amount)
  2106  		status, res = contract.pcall(contract.call.value(1000000000)(system.getItem("addr"), "inc"))
  2107  		return status
  2108  	end
  2109  	function sql()
  2110  		contract.call(system.getItem("addr"), "init")
  2111  		contract.pcall(contract.call, system.getItem("addr"), "pkins1")
  2112  		contract.call(system.getItem("addr"), "pkins2")
  2113  	end
  2114  
  2115  	function sqlget()
  2116  		return contract.call(system.getItem("addr"), "pkget")
  2117  	end
  2118  
  2119  	function getOrigin()
  2120  		return contract.call(system.getItem("addr"), "getOrigin")
  2121  	end
  2122  	abi.register(add, dadd, get, dget, send, sql, sqlget, getOrigin)
  2123  	abi.payable(constructor,add)
  2124  	`
  2125  	err = bc.ConnectBlock(
  2126  		NewLuaTxDef("ktlee", "caller", 10, definition2).
  2127  			Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("counter")))),
  2128  		NewLuaTxCall("ktlee", "caller", 15, `{"Name":"add", "Args":[]}`),
  2129  		NewLuaTxCall("ktlee", "caller", 0, `{"Name":"sql", "Args":[]}`),
  2130  	)
  2131  	if err != nil {
  2132  		t.Error(err)
  2133  	}
  2134  	err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "2")
  2135  	if err != nil {
  2136  		t.Error(err)
  2137  	}
  2138  	err = bc.Query("caller", `{"Name":"sqlget", "Args":[]}`, "", "2")
  2139  	if err != nil {
  2140  		t.Error(err)
  2141  	}
  2142  
  2143  	tx := NewLuaTxCall("ktlee", "caller", 0, `{"Name":"getOrigin", "Args":[]}`)
  2144  	_ = bc.ConnectBlock(tx)
  2145  	receipt := bc.getReceipt(tx.hash())
  2146  	if receipt.GetRet() != "\""+types.EncodeAddress(strHash("ktlee"))+"\"" {
  2147  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  2148  	}
  2149  
  2150  	definition3 := `
  2151  	function pass(addr)
  2152  		contract.send(addr, 1)
  2153  	end
  2154  
  2155  	function add(addr, a, b)
  2156  		system.setItem("arg", a)
  2157  		contract.pcall(pass, addr)
  2158  		return a+b
  2159  	end
  2160  
  2161  	function set(addr)
  2162  		contract.send(addr, 1)
  2163  		system.setItem("arg", 2)
  2164  		status, ret  = contract.pcall(add, addr, 1, 2)
  2165  	end
  2166  
  2167  	function set2(addr)
  2168  		contract.send(addr, 1)
  2169  		system.setItem("arg", 2)
  2170  		status, ret  = contract.pcall(add, addar, 1)
  2171  	end
  2172  
  2173  	function get()
  2174  		return system.getItem("arg")
  2175  	end
  2176  	
  2177  	function getBalance()
  2178  		return contract.balance()
  2179  	end
  2180  
  2181  	abi.register(set, set2, get, getBalance)
  2182  	abi.payable(set, set2)
  2183  	`
  2184  
  2185  	bc, err = LoadDummyChain()
  2186  	if err != nil {
  2187  		t.Errorf("failed to create test database: %v", err)
  2188  	}
  2189  	defer bc.Release()
  2190  
  2191  	err = bc.ConnectBlock(
  2192  		NewLuaTxAccount("ktlee", 100),
  2193  		NewLuaTxAccount("bong", 0),
  2194  		NewLuaTxDef("ktlee", "counter", 0, definition3),
  2195  	)
  2196  	if err != nil {
  2197  		t.Error(err)
  2198  	}
  2199  	tx = NewLuaTxCall("ktlee", "counter", 20,
  2200  		fmt.Sprintf(`{"Name":"set", "Args":["%s"]}`, types.EncodeAddress(strHash("bong"))))
  2201  	err = bc.ConnectBlock(tx)
  2202  	if err != nil {
  2203  		t.Error(err)
  2204  	}
  2205  	err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1")
  2206  	if err != nil {
  2207  		t.Error(err)
  2208  	}
  2209  	err = bc.Query("counter", `{"Name":"getBalance", "Args":[]}`, "", "\"18\"")
  2210  	if err != nil {
  2211  		t.Error(err)
  2212  	}
  2213  	state, err := bc.GetAccountState("bong")
  2214  	if state.GetBalanceBigInt().Uint64() != 2 {
  2215  		t.Error("balance error")
  2216  	}
  2217  	tx = NewLuaTxCall("ktlee", "counter", 10,
  2218  		fmt.Sprintf(`{"Name":"set2", "Args":["%s"]}`, types.EncodeAddress(strHash("bong"))))
  2219  	err = bc.ConnectBlock(tx)
  2220  	if err != nil {
  2221  		t.Error(err)
  2222  	}
  2223  	err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "2")
  2224  	if err != nil {
  2225  		t.Error(err)
  2226  	}
  2227  	state, err = bc.GetAccountState("bong")
  2228  	if state.GetBalanceBigInt().Uint64() != 3 {
  2229  		t.Error("balance error")
  2230  	}
  2231  }
  2232  
  2233  func TestPingpongCall(t *testing.T) {
  2234  	definition1 := `
  2235  	function constructor()
  2236  		system.setItem("key",  "empty")
  2237  	end
  2238  	function start(addr)
  2239  		system.setItem("key",  "start")
  2240  		contract.call(addr, "called")
  2241  	end
  2242  
  2243  	function callback()
  2244  		system.setItem("key",  "callback")
  2245  	end
  2246  
  2247  	function get()
  2248  		return system.getItem("key")
  2249  	end
  2250  
  2251  	abi.register(start, callback, get)
  2252  	`
  2253  
  2254  	bc, err := LoadDummyChain()
  2255  	if err != nil {
  2256  		t.Errorf("failed to create test database: %v", err)
  2257  	}
  2258  	defer bc.Release()
  2259  
  2260  	err = bc.ConnectBlock(
  2261  		NewLuaTxAccount("ktlee", 100),
  2262  		NewLuaTxDef("ktlee", "a", 0, definition1),
  2263  	)
  2264  
  2265  	definition2 := `
  2266  	function constructor(addr)
  2267  		system.setItem("key",  "empty")
  2268  		system.setItem("addr",  addr)
  2269  	end
  2270  
  2271  	function called()
  2272  		system.setItem("key",  "called")
  2273  		contract.call(system.getItem("addr"), "callback")
  2274  	end
  2275  
  2276  	function get()
  2277  		return system.getItem("key")
  2278  	end
  2279  
  2280  	abi.register(called, get)
  2281  	`
  2282  	err = bc.ConnectBlock(
  2283  		NewLuaTxDef("ktlee", "b", 0, definition2).
  2284  			Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("a")))),
  2285  	)
  2286  	if err != nil {
  2287  		t.Error(err)
  2288  	}
  2289  	tx := NewLuaTxCall("ktlee", "a", 0,
  2290  		fmt.Sprintf(`{"Name":"start", "Args":["%s"]}`, types.EncodeAddress(strHash("b"))))
  2291  	_ = bc.ConnectBlock(tx)
  2292  	err = bc.Query("a", `{"Name":"get", "Args":[]}`, "", `"callback"`)
  2293  	if err != nil {
  2294  		t.Error(err)
  2295  	}
  2296  	err = bc.Query("b", `{"Name":"get", "Args":[]}`, "", `"called"`)
  2297  	if err != nil {
  2298  		t.Error(err)
  2299  	}
  2300  }
  2301  
  2302  func TestArrayArg(t *testing.T) {
  2303  	definition1 := `
  2304  	function copy(arr)
  2305  		assert(type(arr) == "table", "table expected")
  2306  		local rv = {}
  2307  		for i, v in ipairs(arr) do
  2308  			table.insert(rv, i, v)
  2309          end
  2310  		return rv
  2311  	end
  2312  	function two_arr(arr1, arr2)
  2313  		assert(type(arr1) == "table", "table expected")
  2314  		assert(type(arr2) == "table", "table expected")
  2315  		local rv = {}
  2316  		table.insert(rv, 1, #arr1)
  2317  		table.insert(rv, 2, #arr2)
  2318  		return rv
  2319  	end
  2320  	function mixed_args(arr1, map1, n)
  2321  		assert(type(arr1) == "table", "table expected")
  2322  		assert(type(map1) == "table", "table expected")
  2323  		local rv = {}
  2324  		table.insert(rv, 1, arr1)
  2325  		table.insert(rv, 2, map1)
  2326  		table.insert(rv, 3, n)
  2327  		return rv
  2328  	end
  2329  
  2330  	abi.register(copy, two_arr, mixed_args)
  2331  	`
  2332  
  2333  	bc, err := LoadDummyChain()
  2334  	if err != nil {
  2335  		t.Errorf("failed to create test database: %v", err)
  2336  	}
  2337  	defer bc.Release()
  2338  
  2339  	err = bc.ConnectBlock(
  2340  		NewLuaTxAccount("ktlee", 100),
  2341  		NewLuaTxDef("ktlee", "a", 0, definition1),
  2342  	)
  2343  	if err != nil {
  2344  		t.Error(err)
  2345  	}
  2346  	err = bc.Query("a", `{"Name": "copy", "Args":[1, 2, 3]}`, "table expected", "")
  2347  	if err != nil {
  2348  		t.Error(err)
  2349  	}
  2350  	err = bc.Query("a", `{"Name": "copy", "Args":[[1, 2, 3]]}`, "", "[1,2,3]")
  2351  	if err != nil {
  2352  		t.Error(err)
  2353  	}
  2354  	err = bc.Query("a", `{"Name": "two_arr", "Args":[[1, 2, 3],[4, 5]]}`, "", "[3,2]")
  2355  	if err != nil {
  2356  		t.Error(err)
  2357  	}
  2358  	err = bc.Query("a", `{"Name": "mixed_args", "Args":[[1, 2, 3], {"name": "kslee", "age": 39}, 7]}`,
  2359  		"",
  2360  		`[[1,2,3],{"age":39,"name":"kslee"},7]`,
  2361  	)
  2362  	if err != nil {
  2363  		t.Error(err)
  2364  	}
  2365  	err = bc.Query("a", `{"Name": "mixed_args", "Args":[
  2366  [[1, 2, 3],["first", "second"]],
  2367  {"name": "kslee", "age": 39, "address": {"state": "XXX-do", "city": "YYY-si"}},
  2368  "end"
  2369  ]}`,
  2370  		"",
  2371  		`[[[1,2,3],["first","second"]],{"address":{"city":"YYY-si","state":"XXX-do"},"age":39,"name":"kslee"},"end"]`,
  2372  	)
  2373  	if err != nil {
  2374  		t.Error(err)
  2375  	}
  2376  	err = bc.Query("a", `{"Name": "mixed_args", "Args":[
  2377  [{"name": "wook", "age": 50}, {"name": "hook", "age": 42}],
  2378  {"name": "kslee", "age": 39, "scores": [10, 20, 30, 40, 50]},
  2379  "hmm..."
  2380  ]}`,
  2381  		"",
  2382  		`[[{"age":50,"name":"wook"},{"age":42,"name":"hook"}],{"age":39,"name":"kslee","scores":[10,20,30,40,50]},"hmm..."]`,
  2383  	)
  2384  	if err != nil {
  2385  		t.Error(err)
  2386  	}
  2387  }
  2388  
  2389  func TestAbi(t *testing.T) {
  2390  	errMsg := "no exported functions"
  2391  
  2392  	noAbi := `
  2393  	function dummy()
  2394  		system.print("dummy")
  2395  	end`
  2396  
  2397  	bc, err := LoadDummyChain()
  2398  	if err != nil {
  2399  		t.Errorf("failed to create test database: %v", err)
  2400  	}
  2401  	defer bc.Release()
  2402  
  2403  	err = bc.ConnectBlock(
  2404  		NewLuaTxAccount("ktlee", 100),
  2405  		NewLuaTxDef("ktlee", "a", 0, noAbi),
  2406  	)
  2407  	if err == nil {
  2408  		t.Errorf("expected: %s, but got: nil", errMsg)
  2409  	} else if !strings.Contains(err.Error(), "no exported functions") {
  2410  		t.Errorf("expected: %s, but got: %s", errMsg, err.Error())
  2411  	}
  2412  
  2413  	empty := `
  2414  	function dummy()
  2415  		system.print("dummy")
  2416  	end
  2417  	abi.register()`
  2418  
  2419  	err = bc.ConnectBlock(
  2420  		NewLuaTxDef("ktlee", "a", 0, empty),
  2421  	)
  2422  	if err == nil {
  2423  		t.Errorf("expected: %s, but got: nil", errMsg)
  2424  	} else if !strings.Contains(err.Error(), "no exported functions.") {
  2425  		t.Errorf("expected: %s, but got: %s", errMsg, err.Error())
  2426  	}
  2427  
  2428  	localFunc := `
  2429  	function dummy()
  2430  		system.print("dummy")
  2431  	end
  2432  	local function helper()
  2433  		system.print("helper")
  2434  	end
  2435  	abi.register(helper)`
  2436  
  2437  	err = bc.ConnectBlock(
  2438  		NewLuaTxDef("ktlee", "a", 0, localFunc),
  2439  	)
  2440  	if err == nil {
  2441  		t.Errorf("expected: %s, but got: nil", errMsg)
  2442  	} else if !strings.Contains(err.Error(), "global function expected") {
  2443  		t.Errorf("expected: %s, but got: %s", errMsg, err.Error())
  2444  	}
  2445  }
  2446  
  2447  func TestMapKey(t *testing.T) {
  2448  	definition := `
  2449  	state.var{
  2450  		counts = state.map()
  2451  	}
  2452  	function setCount(key, value)
  2453  		counts[key] = value
  2454  	end
  2455  	function getCount(key)
  2456  		return counts[key]
  2457  	end
  2458  	function delCount(key)
  2459  		counts:delete(key)
  2460  	end
  2461  	abi.register(setCount, getCount, delCount)
  2462  `
  2463  	bc, err := LoadDummyChain()
  2464  	if err != nil {
  2465  		t.Errorf("failed to create test database: %v", err)
  2466  	}
  2467  	defer bc.Release()
  2468  
  2469  	_ = bc.ConnectBlock(
  2470  		NewLuaTxAccount("ktlee", 100),
  2471  		NewLuaTxDef("ktlee", "a", 0, definition),
  2472  	)
  2473  
  2474  	err = bc.Query("a", `{"Name":"getCount", "Args":[1]}`, "", "{}")
  2475  	if err != nil {
  2476  		t.Error(err)
  2477  	}
  2478  
  2479  	err = bc.ConnectBlock(
  2480  		NewLuaTxCall("ktlee", "a", 0, `{"Name":"setCount", "Args":[1, 10]}`),
  2481  		NewLuaTxCall("ktlee", "a", 0, `{"Name":"setCount", "Args":["1", 20]}`).Fail("(number expected, got string)"),
  2482  		NewLuaTxCall("ktlee", "a", 0, `{"Name":"setCount", "Args":[1.1, 30]}`),
  2483  	)
  2484  	if err != nil {
  2485  		t.Error(err)
  2486  	}
  2487  	err = bc.Query("a", `{"Name":"getCount", "Args":["1"]}`, "(number expected, got string)", "")
  2488  	if err != nil {
  2489  		t.Error(err)
  2490  	}
  2491  	err = bc.Query("a", `{"Name":"getCount", "Args":[1]}`, "", "10")
  2492  	if err != nil {
  2493  		t.Error(err)
  2494  	}
  2495  	err = bc.Query("a", `{"Name":"getCount", "Args":[1.1]}`, "", "30")
  2496  	if err != nil {
  2497  		t.Error(err)
  2498  	}
  2499  	err = bc.ConnectBlock(
  2500  		NewLuaTxCall("ktlee", "a", 0,
  2501  			`{"Name":"setCount", "Args":[true, 40]}`,
  2502  		).Fail(`invalid key type: 'boolean', state.map: 'counts'`),
  2503  	)
  2504  	if err != nil {
  2505  		t.Error(err)
  2506  	}
  2507  	err = bc.ConnectBlock(
  2508  		NewLuaTxCall("ktlee", "a", 0, `{"Name":"delCount", "Args":[1.1]}`),
  2509  	)
  2510  	if err != nil {
  2511  		t.Error(err)
  2512  	}
  2513  	err = bc.Query("a", `{"Name":"getCount", "Args":[1.1]}`, "", "{}")
  2514  	if err != nil {
  2515  		t.Error(err)
  2516  	}
  2517  	err = bc.Query("a", `{"Name":"getCount", "Args":[2]}`, "", "{}")
  2518  	if err != nil {
  2519  		t.Error(err)
  2520  	}
  2521  
  2522  	_ = bc.ConnectBlock(
  2523  		NewLuaTxDef("ktlee", "x", 0, definition),
  2524  	)
  2525  	err = bc.ConnectBlock(
  2526  		NewLuaTxCall("ktlee", "x", 0, `{"Name":"setCount", "Args":["1", 10]}`),
  2527  		NewLuaTxCall("ktlee", "x", 0, `{"Name":"setCount", "Args":[1, 20]}`).Fail("string expected, got number)"),
  2528  		NewLuaTxCall("ktlee", "x", 0, `{"Name":"setCount", "Args":["third", 30]}`),
  2529  	)
  2530  	if err != nil {
  2531  		t.Error(err)
  2532  	}
  2533  	err = bc.Query("x", `{"Name":"getCount", "Args":["1"]}`, "", "10")
  2534  	if err != nil {
  2535  		t.Error(err)
  2536  	}
  2537  	err = bc.Query("x", `{"Name":"getCount", "Args":["third"]}`, "", "30")
  2538  	if err != nil {
  2539  		t.Error(err)
  2540  	}
  2541  }
  2542  
  2543  func TestStateVarFieldUpdate(t *testing.T) {
  2544  	src := `
  2545  state.var{
  2546     Person = state.value()
  2547  }
  2548  
  2549  function constructor()
  2550    Person:set({ name = "kslee", age = 38, address = "blahblah..." })
  2551  end
  2552  
  2553  function InvalidUpdateAge(age)
  2554    Person:get().age = age
  2555  end
  2556  
  2557  function ValidUpdateAge(age)
  2558    local p = Person:get()
  2559    p.age = age
  2560    Person:set(p)
  2561  end
  2562  
  2563  function GetPerson()
  2564    return Person:get()
  2565  end
  2566  
  2567  abi.register(InvalidUpdateAge, ValidUpdateAge, GetPerson)
  2568  `
  2569  	bc, err := LoadDummyChain()
  2570  	if err != nil {
  2571  		t.Errorf("failed to create test database: %v", err)
  2572  	}
  2573  	defer bc.Release()
  2574  
  2575  	err = bc.ConnectBlock(
  2576  		NewLuaTxAccount("ktlee", 100),
  2577  		NewLuaTxDef("ktlee", "c", 0, src),
  2578  	)
  2579  	if err != nil {
  2580  		t.Error(err)
  2581  	}
  2582  	err = bc.ConnectBlock(
  2583  		NewLuaTxCall("ktlee", "c", 0, `{"Name":"InvalidUpdateAge", "Args":[10]}`),
  2584  	)
  2585  	if err != nil {
  2586  		t.Error(err)
  2587  	}
  2588  	err = bc.Query("c", `{"Name":"GetPerson"}`, "",
  2589  		`{"address":"blahblah...","age":38,"name":"kslee"}`,
  2590  	)
  2591  	if err != nil {
  2592  		t.Error(err)
  2593  	}
  2594  	err = bc.ConnectBlock(
  2595  		NewLuaTxCall("ktlee", "c", 0, `{"Name":"ValidUpdateAge", "Args":[10]}`),
  2596  	)
  2597  	if err != nil {
  2598  		t.Error(err)
  2599  	}
  2600  	err = bc.Query("c", `{"Name":"GetPerson"}`, "",
  2601  		`{"address":"blahblah...","age":10,"name":"kslee"}`,
  2602  	)
  2603  	if err != nil {
  2604  		t.Error(err)
  2605  	}
  2606  }
  2607  
  2608  func TestDatetime(t *testing.T) {
  2609  	src := `
  2610  state.var {
  2611      cdate = state.value()
  2612  }
  2613  
  2614  function constructor()
  2615  	cdate:set(906000490)
  2616  end
  2617  
  2618  function CreateDate()
  2619  	return system.date("%c", cdate:get())
  2620  end
  2621  
  2622  function Extract(fmt)
  2623  	return system.date(fmt, cdate:get())
  2624  end
  2625  
  2626  function Difftime()
  2627  	system.print(system.date("%c", cdate:get()))
  2628  	s = system.date("*t", cdate:get())
  2629  	system.print(s)
  2630  	s.hour = 2 
  2631  	s.min = 0
  2632  	s.sec = 0
  2633  	system.print(system.date("*t", system.time(s)))
  2634  	return system.difftime(cdate:get(), system.time(s))
  2635  end
  2636  
  2637  abi.register(CreateDate, Extract, Difftime)
  2638  `
  2639  	bc, err := LoadDummyChain()
  2640  	if err != nil {
  2641  		t.Errorf("failed to create test database: %v", err)
  2642  	}
  2643  	defer bc.Release()
  2644  
  2645  	err = bc.ConnectBlock(
  2646  		NewLuaTxAccount("ktlee", 100),
  2647  		NewLuaTxDef("ktlee", "datetime", 0, src),
  2648  	)
  2649  	if err != nil {
  2650  		t.Error(err)
  2651  	}
  2652  	err = bc.Query("datetime", `{"Name": "CreateDate"}`, "", `"1998-09-17 02:48:10"`)
  2653  	if err != nil {
  2654  		t.Error(err)
  2655  	}
  2656  	err = bc.Query("datetime", `{"Name": "Extract", "Args":["%x"]}`, "", `"09/17/98"`)
  2657  	if err != nil {
  2658  		t.Error(err)
  2659  	}
  2660  	err = bc.Query("datetime", `{"Name": "Extract", "Args":["%X"]}`, "", `"02:48:10"`)
  2661  	if err != nil {
  2662  		t.Error(err)
  2663  	}
  2664  	err = bc.Query("datetime", `{"Name": "Extract", "Args":["%A"]}`, "", `"Thursday"`)
  2665  	if err != nil {
  2666  		t.Error(err)
  2667  	}
  2668  	err = bc.Query("datetime", `{"Name": "Extract", "Args":["%I:%M:%S %p"]}`, "", `"02:48:10 AM"`)
  2669  	if err != nil {
  2670  		t.Error(err)
  2671  	}
  2672  	err = bc.Query("datetime", `{"Name": "Difftime"}`, "", `2890`)
  2673  	if err != nil {
  2674  		t.Error(err)
  2675  	}
  2676  }
  2677  
  2678  func TestDynamicArray(t *testing.T) {
  2679  	zeroLen := `
  2680  state.var {
  2681      fixedArray = state.array(0)
  2682  }
  2683  
  2684  function Length()
  2685  	return fixedArray:length()
  2686  end
  2687  
  2688  abi.register(Length)
  2689  `
  2690  	bc, err := LoadDummyChain()
  2691  	if err != nil {
  2692  		t.Errorf("failed to create test database: %v", err)
  2693  	}
  2694  	defer bc.Release()
  2695  
  2696  	_ = bc.ConnectBlock(
  2697  		NewLuaTxAccount("ktlee", 100),
  2698  	)
  2699  	err = bc.ConnectBlock(
  2700  		NewLuaTxDef("ktlee", "zeroLen", 0, zeroLen),
  2701  	)
  2702  	if err == nil {
  2703  		t.Error("expected: the array length must be greater than zero")
  2704  	}
  2705  	if !strings.Contains(err.Error(), "the array length must be greater than zero") {
  2706  		t.Errorf(err.Error())
  2707  	}
  2708  
  2709  	dArr := `
  2710  state.var {
  2711      dArr = state.array()
  2712  }
  2713  
  2714  function Append(val)
  2715  	dArr:append(val)
  2716  end
  2717  
  2718  function Get(idx)
  2719  	return dArr[idx]
  2720  end
  2721  
  2722  function Set(idx, val)
  2723  	dArr[idx] = val
  2724  end
  2725  
  2726  function Length()
  2727  	return dArr:length()
  2728  end
  2729  
  2730  abi.register(Append, Get, Set, Length)
  2731  `
  2732  	tx := NewLuaTxDef("ktlee", "dArr", 0, dArr)
  2733  	err = bc.ConnectBlock(tx)
  2734  	if err != nil {
  2735  		t.Error(err)
  2736  	}
  2737  	err = bc.Query("dArr", `{"Name": "Length"}`, "", "0")
  2738  	if err != nil {
  2739  		t.Error(err)
  2740  	}
  2741  	err = bc.ConnectBlock(
  2742  		NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [10]}`),
  2743  		NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [20]}`),
  2744  	)
  2745  	if err != nil {
  2746  		t.Error(err)
  2747  	}
  2748  	err = bc.Query("dArr", `{"Name": "Get", "Args": [1]}`, "", "10")
  2749  	if err != nil {
  2750  		t.Error(err)
  2751  	}
  2752  	err = bc.Query("dArr", `{"Name": "Get", "Args": [2]}`, "", "20")
  2753  	if err != nil {
  2754  		t.Error(err)
  2755  	}
  2756  	err = bc.Query("dArr", `{"Name": "Get", "Args": [3]}`, "index out of range", "")
  2757  	if err != nil {
  2758  		t.Error(err)
  2759  	}
  2760  	err = bc.Query("dArr", `{"Name": "Length"}`, "", "2")
  2761  	if err != nil {
  2762  		t.Error(err)
  2763  	}
  2764  	err = bc.ConnectBlock(
  2765  		NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [30]}`),
  2766  		NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [40]}`),
  2767  	)
  2768  	err = bc.Query("dArr", `{"Name": "Length"}`, "", "4")
  2769  	if err != nil {
  2770  		t.Error(err)
  2771  	}
  2772  	err = bc.ConnectBlock(
  2773  		NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Set", "Args": [3, 50]}`),
  2774  	)
  2775  	err = bc.Query("dArr", `{"Name": "Get", "Args": [3]}`, "", "50")
  2776  	if err != nil {
  2777  		t.Error(err)
  2778  	}
  2779  }
  2780  
  2781  func TestDupVar(t *testing.T) {
  2782  	dupVar := `
  2783  state.var{
  2784  	Var1 = state.value(),
  2785  }
  2786  function GetVar1()
  2787  	return Var1:get()
  2788  end
  2789  state.var{
  2790  	Var1 = state.value(),
  2791  }
  2792  abi.register(GetVar1)
  2793  `
  2794  	bc, err := LoadDummyChain()
  2795  	if err != nil {
  2796  		t.Errorf("failed to create test database: %v", err)
  2797  	}
  2798  	defer bc.Release()
  2799  
  2800  	err = bc.ConnectBlock(
  2801  		NewLuaTxAccount("ktlee", 100),
  2802  		NewLuaTxDef("ktlee", "dupVar", 0, dupVar),
  2803  	)
  2804  	if err == nil {
  2805  		t.Error("duplicated variable: 'Var1'")
  2806  	}
  2807  	if !strings.Contains(err.Error(), "duplicated variable: 'Var1'") {
  2808  		t.Error(err)
  2809  	}
  2810  
  2811  	dupVar = `
  2812  state.var{
  2813  	Var1 = state.value(),
  2814  }
  2815  function GetVar1()
  2816  	return Var1:get()
  2817  end
  2818  function Work()
  2819  	state.var{
  2820  		Var1 = state.value(),
  2821  	}
  2822  end
  2823  abi.register(GetVar1, Work)
  2824  `
  2825  	err = bc.ConnectBlock(
  2826  		NewLuaTxDef("ktlee", "dupVar1", 0, dupVar),
  2827  	)
  2828  	if err != nil {
  2829  		t.Error(err)
  2830  	}
  2831  	err = bc.ConnectBlock(
  2832  		NewLuaTxCall("ktlee", "dupVar1", 0, `{"Name": "Work"}`).Fail("duplicated variable: 'Var1'"),
  2833  	)
  2834  
  2835  	if err != nil {
  2836  		t.Error(err)
  2837  	}
  2838  }
  2839  
  2840  func TestCrypto(t *testing.T) {
  2841  	src := `
  2842  function get(a)
  2843  	return crypto.sha256(a)
  2844  end
  2845  
  2846  function checkEther()
  2847  	return crypto.ecverify("0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
  2848  "0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301",
  2849  "0xbcf9061f21320aa7e824b00d0152398b2d7a6e44")
  2850  end
  2851  
  2852  function checkAergo()
  2853  	return crypto.ecverify("11e96f2b58622a0ce815b81f94da04ae7a17ba17602feb1fd5afa4b9f2467960",
  2854  "304402202e6d5664a87c2e29856bf8ff8b47caf44169a2a4a135edd459640be5b1b6ef8102200d8ea1f6f9ecdb7b520cdb3cc6816d773df47a1820d43adb4b74fb879fb27402",
  2855  "AmPbWrQbtQrCaJqLWdMtfk2KiN83m2HFpBbQQSTxqqchVv58o82i")
  2856  end
  2857  
  2858  function keccak256(s)
  2859  	return crypto.keccak256(s)
  2860  end
  2861  
  2862  abi.register(get, checkEther, checkAergo, keccak256)
  2863  `
  2864  	bc, err := LoadDummyChain()
  2865  	if err != nil {
  2866  		t.Errorf("failed to create test database: %v", err)
  2867  	}
  2868  	defer bc.Release()
  2869  
  2870  	err = bc.ConnectBlock(
  2871  		NewLuaTxAccount("ktlee", 100),
  2872  		NewLuaTxDef("ktlee", "crypto", 0, src),
  2873  	)
  2874  	err = bc.Query("crypto", `{"Name": "get", "Args" : ["ab\u0000\u442a"]}`, "", `"0xc58f6dca13e4bba90a326d8605042862fe87c63a64a9dd0e95608a2ee68dc6f0"`)
  2875  	if err != nil {
  2876  		t.Error(err)
  2877  	}
  2878  	err = bc.Query("crypto", `{"Name": "get", "Args" : ["0x616200e490aa"]}`, "", `"0xc58f6dca13e4bba90a326d8605042862fe87c63a64a9dd0e95608a2ee68dc6f0"`)
  2879  	if err != nil {
  2880  		t.Error(err)
  2881  	}
  2882  	err = bc.Query("crypto", `{"Name": "checkEther", "Args" : []}`, "", `true`)
  2883  	if err != nil {
  2884  		t.Error(err)
  2885  	}
  2886  
  2887  	err = bc.Query("crypto", `{"Name": "checkAergo", "Args" : []}`, "", `true`)
  2888  	if err != nil {
  2889  		t.Error(err)
  2890  	}
  2891  
  2892  	err = bc.Query(
  2893  		"crypto",
  2894  		`{"Name": "keccak256", "Args" : ["0x616263"]}`,
  2895  		"",
  2896  		`"0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45"`)
  2897  	if err != nil {
  2898  		t.Error(err)
  2899  	}
  2900  
  2901  	err = bc.Query(
  2902  		"crypto",
  2903  		`{"Name": "keccak256", "Args" : ["0x616572676F"]}`,
  2904  		"",
  2905  		`"0xe98bb03ab37161f8bbfe131f711dcccf3002a9cd9ec31bbd52edf181f7ab09a0"`)
  2906  	if err != nil {
  2907  		t.Error(err)
  2908  	}
  2909  }
  2910  
  2911  func TestPayable(t *testing.T) {
  2912  	src := `
  2913  state.var {
  2914  	Data = state.value()
  2915  }
  2916  function save(data)
  2917  	Data:set(data)
  2918  end
  2919  function load()
  2920  	return Data:get()
  2921  end
  2922  
  2923  abi.register(load)
  2924  abi.payable(save)
  2925  `
  2926  	bc, err := LoadDummyChain()
  2927  	if err != nil {
  2928  		t.Errorf("failed to create test database: %v", err)
  2929  	}
  2930  	defer bc.Release()
  2931  
  2932  	err = bc.ConnectBlock(
  2933  		NewLuaTxAccount("ktlee", 100),
  2934  	)
  2935  
  2936  	err = bc.ConnectBlock(
  2937  		NewLuaTxDef("ktlee", "payable", 1, src),
  2938  	)
  2939  	if err == nil {
  2940  		t.Error("expected: 'constructor' is not payable")
  2941  	} else {
  2942  		if !strings.Contains(err.Error(), "'constructor' is not payable") {
  2943  			t.Error(err)
  2944  		}
  2945  	}
  2946  	err = bc.ConnectBlock(
  2947  		NewLuaTxCall("ktlee", "payable", 0, `{"Name":"save", "Args": ["blahblah"]}`).Fail("not found contract"),
  2948  	)
  2949  	if err != nil {
  2950  		t.Error(err)
  2951  	}
  2952  	err = bc.ConnectBlock(
  2953  		NewLuaTxDef("ktlee", "payable", 0, src),
  2954  		NewLuaTxCall("ktlee", "payable", 0, `{"Name":"save", "Args": ["blahblah"]}`),
  2955  	)
  2956  	if err != nil {
  2957  		t.Error(err)
  2958  	}
  2959  	err = bc.Query("payable", `{"Name":"load"}`, "", `"blahblah"`)
  2960  	if err != nil {
  2961  		t.Error(err)
  2962  	}
  2963  	err = bc.ConnectBlock(
  2964  		NewLuaTxCall("ktlee", "payable", 1, `{"Name":"save", "Args": ["payed"]}`),
  2965  	)
  2966  	if err != nil {
  2967  		t.Error(err)
  2968  	}
  2969  	err = bc.Query("payable", `{"Name":"load"}`, "", `"payed"`)
  2970  	if err != nil {
  2971  		t.Error(err)
  2972  	}
  2973  }
  2974  
  2975  func TestDefault(t *testing.T) {
  2976  	src := `
  2977  function default()
  2978  	return "default"
  2979  end
  2980  abi.register(default)
  2981  `
  2982  	bc, err := LoadDummyChain()
  2983  	if err != nil {
  2984  		t.Errorf("failed to create test database: %v", err)
  2985  	}
  2986  	defer bc.Release()
  2987  
  2988  	err = bc.ConnectBlock(
  2989  		NewLuaTxAccount("ktlee", 100),
  2990  		NewLuaTxDef("ktlee", "default", 0, src),
  2991  	)
  2992  	if err != nil {
  2993  		t.Error(err)
  2994  	}
  2995  	tx := NewLuaTxCall("ktlee", "default", 0, "")
  2996  	err = bc.ConnectBlock(tx)
  2997  	receipt := bc.getReceipt(tx.hash())
  2998  	if receipt.GetRet() != `"default"` {
  2999  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  3000  	}
  3001  	err = bc.ConnectBlock(
  3002  		NewLuaTxCall("ktlee", "default", 1, "").Fail(`'default' is not payable`),
  3003  	)
  3004  	if err != nil {
  3005  		t.Error(err)
  3006  	}
  3007  	err = bc.Query("default", `{"Name":"a"}`, "not found function: a", "")
  3008  	if err != nil {
  3009  		t.Error(err)
  3010  	}
  3011  }
  3012  
  3013  func TestBignum(t *testing.T) {
  3014  	bigNum := `
  3015  function test(addr)
  3016  	bal = contract.balance()
  3017  	contract.send(addr, bal / 2)
  3018  	return contract.balance()
  3019  end
  3020  
  3021  function sendS(addr)
  3022  	contract.send(addr, "1 gaer 99999")
  3023  	return contract.balance()
  3024  end
  3025  
  3026  function testBignum()
  3027  	bg = bignum.number("999999999999999999999999999999")
  3028  	system.setItem("big", bg)
  3029  	bi = system.getItem("big")
  3030  	return tostring(bi)
  3031  end
  3032  
  3033  function argBignum(a)
  3034  	b = a + 1
  3035  	return tostring(b)
  3036  end
  3037  
  3038  function calladdBignum(addr, a)
  3039  	return tostring(contract.call(addr, "add", a, 2) + 3)
  3040  end
  3041  
  3042  function checkBignum()
  3043  	a = 1
  3044  	b = bignum.number(1)
  3045  	
  3046  	return bignum.isbignum(a), bignum.isbignum(b), bignum.isbignum("2333")
  3047  end
  3048  function calcBignum()
  3049  	bg1 = bignum.number("999999999999999999999999999999")
  3050  	bg2 = bignum.number("999999999999999999999999999999")
  3051  	bg3 = bg1 + bg2
  3052  	bg4 = bg1 * 2
  3053  	bg5 = 2 * bg1
  3054  	n1 = 999999999999999
  3055  	system.print(n1)
  3056  	bg6 = bignum.number(n1)
  3057  	assert (bg3 == bg4 and bg4 == bg5)
  3058  	bg5 = bg1 - bg3 
  3059  	assert (bignum.isneg(bg5) and bg5 == bignum.neg(bg1))
  3060  	system.print(bg3, bg5, bg6)
  3061  	bg6 = bignum.number(1)
  3062  	assert (bg6 > bg5)
  3063  	a = bignum.number(2)
  3064  	b = bignum.number(8)
  3065  	pow = a ^ b
  3066  	system.print(pow, a, b)
  3067  	assert(pow == bignum.number(256) and a == bignum.number(2) and b == bignum.number(8))
  3068  	assert(bignum.compare(bg6, 1) == 0)
  3069  	system.print((bg6 == 1), bignum.isbignum(pow))
  3070  	div1 = bignum.number(3)/2
  3071  	assert(bignum.compare(div1, 1) == 0)
  3072  	div = bg6 / 0
  3073  end
  3074  
  3075  function negativeBignum()
  3076  	bg1 = bignum.number("-2")
  3077  	bg2 = bignum.sqrt(bg1)
  3078  end
  3079  
  3080  function byteBignum()
  3081  	 state.var {
  3082          value = state.value()
  3083      }
  3084  	value = bignum.tobyte(bignum.number("177"))
  3085  	return bignum.frombyte(value)
  3086  end
  3087  
  3088  function constructor()
  3089  end
  3090  
  3091  abi.register(test, sendS, testBignum, argBignum, calladdBignum, checkBignum, calcBignum, negativeBignum, byteBignum)
  3092  abi.payable(constructor)
  3093  `
  3094  	callee := `
  3095  	function add(a, b)
  3096  		return a + b
  3097  	end
  3098  	abi.register(add)
  3099  	`
  3100  
  3101  	bc, err := LoadDummyChain()
  3102  	if err != nil {
  3103  		t.Errorf("failed to create test database: %v", err)
  3104  	}
  3105  	defer bc.Release()
  3106  
  3107  	err = bc.ConnectBlock(
  3108  		NewLuaTxAccount("ktlee", 1000000000000),
  3109  		NewLuaTxDef("ktlee", "bigNum", 50000000000, bigNum),
  3110  		NewLuaTxDef("ktlee", "add", 0, callee),
  3111  	)
  3112  	if err != nil {
  3113  		t.Error(err)
  3114  	}
  3115  	tx := NewLuaTxCall("ktlee", "bigNum", 0, fmt.Sprintf(`{"Name":"test", "Args":["%s"]}`, types.EncodeAddress(strHash("ktlee"))))
  3116  	err = bc.ConnectBlock(tx)
  3117  	if err != nil {
  3118  		t.Error(err)
  3119  	}
  3120  	receipt := bc.getReceipt(tx.hash())
  3121  	if receipt.GetRet() != `"25000000000"` {
  3122  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  3123  	}
  3124  	tx = NewLuaTxCall("ktlee", "bigNum", 0, fmt.Sprintf(`{"Name":"sendS", "Args":["%s"]}`, types.EncodeAddress(strHash("ktlee"))))
  3125  	err = bc.ConnectBlock(tx)
  3126  	if err != nil {
  3127  		t.Error(err)
  3128  	}
  3129  	receipt = bc.getReceipt(tx.hash())
  3130  	if receipt.GetRet() != `"23999900001"` {
  3131  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  3132  	}
  3133  	tx = NewLuaTxCall("ktlee", "bigNum", 0, `{"Name":"testBignum", "Args":[]}`)
  3134  	err = bc.ConnectBlock(tx)
  3135  	if err != nil {
  3136  		t.Error(err)
  3137  	}
  3138  	receipt = bc.getReceipt(tx.hash())
  3139  	if receipt.GetRet() != `"999999999999999999999999999999"` {
  3140  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  3141  	}
  3142  	err = bc.Query("bigNum", `{"Name":"argBignum", "Args":[{"_bignum":"99999999999999999999999999"}]}`, "", `"100000000000000000000000000"`)
  3143  	if err != nil {
  3144  		t.Error(err)
  3145  	}
  3146  	err = bc.Query("bigNum", fmt.Sprintf(`{"Name":"calladdBignum", "Args":["%s", {"_bignum":"999999999999999999"}]}`, types.EncodeAddress(strHash("add"))), "", `"1000000000000000004"`)
  3147  	if err != nil {
  3148  		t.Error(err)
  3149  	}
  3150  	err = bc.Query("bigNum", `{"Name":"checkBignum"}`, "", `[false,true,false]`)
  3151  	if err != nil {
  3152  		t.Error(err)
  3153  	}
  3154  	err = bc.Query("bigNum", `{"Name":"calcBignum"}`, "bignum divide by zero", "")
  3155  	if err != nil {
  3156  		t.Error(err)
  3157  	}
  3158  	err = bc.Query("bigNum", `{"Name":"negativeBignum"}`, "bignum not allowed negative value", "")
  3159  	if err != nil {
  3160  		t.Error(err)
  3161  	}
  3162  	err = bc.Query("bigNum", `{"Name":"byteBignum"}`, "", `{"_bignum":"177"}`)
  3163  	if err != nil {
  3164  		t.Error(err)
  3165  	}
  3166  }
  3167  
  3168  func TestDeploy(t *testing.T) {
  3169  	deploy := `
  3170  function hello()
  3171  	hello = [[
  3172  function hello(say)
  3173  	return "Hello " .. say 
  3174  end
  3175  
  3176  local type_check = {}
  3177  function type_check.isValidAddress(address)
  3178      -- check existence of invalid alphabets
  3179      if nil ~= string.match(address, '[^123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]') then
  3180          return false
  3181      end
  3182      -- check lenght is in range
  3183      if 52 ~= string.len(address) then
  3184          return false
  3185      end
  3186      -- TODO add checksum verification?
  3187      return true
  3188  end
  3189  function type_check.isValidNumber(value)
  3190      if nil ~= string.match(value, '[^0123456789]') then
  3191          return false
  3192      end
  3193      return true
  3194  end
  3195  
  3196  -- The a bridge token is a mintable and burnable token controlled by
  3197  -- the bridge contract. It represents all tokens locked on the other side of the 
  3198  -- bridge with a 1:1 ratio.
  3199  -- This contract is depoyed by the merkle bridge when a new type of token 
  3200  -- is transfered
  3201  state.var {
  3202      Symbol = state.value(),
  3203      Name = state.value(),
  3204      Decimals = state.value(),
  3205      TotalSupply = state.value(),
  3206      Balances = state.map(),
  3207      Nonces = state.map(),
  3208      -- Contract ID is a unique id that cannot be shared by another contract, even one on a sidechain
  3209      -- This is neeeded for replay protection of signed transfer, because users might have the same private key
  3210      -- on different sidechains
  3211      ContractID = state.value(),
  3212      Owner = state.value(),
  3213  }
  3214  
  3215  function constructor() 
  3216      Symbol:set("TOKEN")
  3217      Name:set("Standard Token on Aergo")
  3218      Decimals:set(18)
  3219      TotalSupply:set(bignum.number(0))
  3220      Owner:set(system.getSender())
  3221      -- contractID is the hash of system.getContractID (prevent replay between contracts on the same chain) and system.getPrevBlockHash (prevent replay between sidechains).
  3222      -- take the first 16 bytes to save size of signed message
  3223      local id = crypto.sha256(system.getContractID()..system.getPrevBlockHash())
  3224      id = string.sub(id, 3, 32)
  3225      ContractID:set(id)
  3226      return true
  3227  end
  3228  
  3229  ---------------------------------------
  3230  -- Transfer sender's token to target 'to'
  3231  -- @type        call
  3232  -- @param to    a target address
  3233  -- @param value string amount of tokens to send
  3234  -- @return      success
  3235  ---------------------------------------
  3236  function transfer(to, value) 
  3237      assert(type_check.isValidNumber(value), "invalid value format (must be string)")
  3238      assert(type_check.isValidAddress(to), "invalid address format: " .. to)
  3239      local from = system.getSender()
  3240      local bvalue = bignum.number(value)
  3241      local b0 = bignum.number(0)
  3242      assert(bvalue > b0, "invalid value")
  3243      assert(to ~= from, "same sender and receiver")
  3244      assert(Balances[from] and bvalue <= Balances[from], "not enough balance")
  3245      Balances[from] = Balances[from] - bvalue
  3246      Nonces[from] = (Nonces[from] or 0) + 1
  3247      Balances[to] = (Balances[to] or b0) + bvalue
  3248      -- TODO event notification
  3249      return true
  3250  end
  3251  
  3252  ---------------------------------------
  3253  -- Transfer tokens according to signed data from the owner
  3254  -- @type  call
  3255  -- @param from      sender's address
  3256  -- @param to        receiver's address
  3257  -- @param value     string amount of token to send in aer
  3258  -- @param nonce     nonce of the sender to prevent replay
  3259  -- @param fee       string fee given to the tx broadcaster
  3260  -- @param deadline  block number before which the tx can be executed
  3261  -- @param signature signature proving sender's consent
  3262  -- @return          success
  3263  ---------------------------------------
  3264  function signed_transfer(from, to, value, nonce, signature, fee, deadline)
  3265      assert(type_check.isValidNumber(value), "invalid value format (must be string)")
  3266      assert(type_check.isValidNumber(fee), "invalid fee format (must be string)")
  3267      local bfee = bignum.number(fee)
  3268      local bvalue = bignum.number(value)
  3269      local b0 = bignum.number(0)
  3270      -- check addresses
  3271      assert(type_check.isValidAddress(to), "invalid address format: " .. to)
  3272      assert(type_check.isValidAddress(from), "invalid address format: " .. from)
  3273      assert(to ~= from, "same sender and receiver")
  3274      -- check amounts, fee
  3275      assert(bfee >= b0, "fee must be positive")
  3276      assert(bvalue >= b0, "value must be positive")
  3277      assert(Balances[from] and (bvalue+bfee) <= Balances[from], "not enough balance")
  3278      -- check deadline
  3279      assert(deadline == 0 or system.getBlockheight() < deadline, "deadline has passed")
  3280      -- check nonce
  3281      if Nonces[from] == nil then Nonces[from] = 0 end
  3282      assert(Nonces[from] == nonce, "nonce is invalid or already spent")
  3283      -- construct signed transfer and verifiy signature
  3284      data = crypto.sha256(to..bignum.tostring(bvalue)..tostring(nonce)..bignum.tostring(bfee)..tostring(deadline)..ContractID:get())
  3285      assert(crypto.ecverify(data, signature, from), "signature of signed transfer is invalid")
  3286      -- execute transfer
  3287      Balances[from] = Balances[from] - bvalue - bfee
  3288      Balances[to] = (Balances[to] or b0) + bvalue
  3289      Balances[system.getOrigin()] = (Balances[system.getOrigin()] or b0) + bfee
  3290      Nonces[from] = Nonces[from] + 1
  3291      -- TODO event notification
  3292      return true
  3293  end
  3294  
  3295  
  3296  ---------------------------------------
  3297  -- mint, burn and signed_burn are specific to the token contract controlled by
  3298  -- the merkle bridge contract and representing transfered assets.
  3299  ---------------------------------------
  3300  
  3301  ---------------------------------------
  3302  -- Mint tokens to 'to'
  3303  -- @type        call
  3304  -- @param to    a target address
  3305  -- @param value string amount of token to mint
  3306  -- @return      success
  3307  ---------------------------------------
  3308  function mint(to, value)
  3309      assert(system.getSender() == Owner:get(), "Only bridge contract can mint")
  3310      assert(type_check.isValidNumber(value), "invalid value format (must be string)")
  3311      local bvalue = bignum.number(value)
  3312      local b0 = bignum.number(0)
  3313      assert(type_check.isValidAddress(to), "invalid address format: " .. to)
  3314      local new_total = TotalSupply:get() + bvalue
  3315      TotalSupply:set(new_total)
  3316      Balances[to] = (Balances[to] or b0) + bvalue;
  3317      -- TODO event notification
  3318      return true
  3319  end
  3320  
  3321  ---------------------------------------
  3322  -- burn the tokens of 'from'
  3323  -- @type        call
  3324  -- @param from  a target address
  3325  -- @param value an amount of token to send
  3326  -- @return      success
  3327  ---------------------------------------
  3328  function burn(from, value)
  3329      assert(system.getSender() == Owner:get(), "Only bridge contract can burn")
  3330      assert(type_check.isValidNumber(value), "invalid value format (must be string)")
  3331      local bvalue = bignum.number(value)
  3332      local b0 = bignum.number(0)
  3333      assert(type_check.isValidAddress(from), "invalid address format: " ..from)
  3334      assert(Balances[from] and bvalue <= Balances[from], "Not enough funds to burn")
  3335      new_total = TotalSupply:get() - bvalue
  3336      TotalSupply:set(new_total)
  3337      Balances[from] = Balances[from] - bvalue
  3338      -- TODO event notification
  3339      return true
  3340  end
  3341  
  3342  ---------------------------------------
  3343  -- signed_burn the tokens of 'from' according to signed data from the owner
  3344  -- @type            call
  3345  -- @param from      a target address
  3346  -- @param value     an amount of token to send
  3347  -- @param nonce     nonce of the sender to prevent replay
  3348  -- @param fee       string fee given to the tx broadcaster
  3349  -- @param deadline  block number before which the tx can be executed
  3350  -- @param signature signature proving sender's consent
  3351  -- @return          success
  3352  ---------------------------------------
  3353  function signed_burn(from, value, nonce, signature, fee, deadline)
  3354      assert(system.getSender() == Owner:get(), "Only bridge contract can burn")
  3355      assert(type_check.isValidNumber(value), "invalid value format (must be string)")
  3356      assert(type_check.isValidNumber(fee), "invalid fee format (must be string)")
  3357      local bfee = bignum.number(fee)
  3358      local bvalue = bignum.number(value)
  3359      local b0 = bignum.number(0)
  3360      -- check addresses
  3361      assert(type_check.isValidAddress(from), "invalid address format: " .. from)
  3362      -- check amounts, fee
  3363      assert(bfee >= b0, "fee must be positive")
  3364      assert(bvalue >= b0, "value must be positive")
  3365      assert(Balances[from] and (bvalue+bfee) <= Balances[from], "not enough balance")
  3366      -- check deadline
  3367      assert(deadline == 0 or system.getBlockheight() < deadline, "deadline has passed")
  3368      -- check nonce
  3369      if Nonces[from] == nil then Nonces[from] = 0 end
  3370      assert(Nonces[from] == nonce, "nonce is invalid or already spent")
  3371      -- construct signed transfer and verifiy signature
  3372      data = crypto.sha256(system.getSender()..bignum.tostring(bvalue)..tostring(nonce)..bignum.tostring(bfee)..tostring(deadline)..ContractID:get())
  3373      assert(crypto.ecverify(data, signature, from), "signature of signed transfer is invalid")
  3374      -- execute burn
  3375      new_total = TotalSupply:get() - bvalue
  3376      TotalSupply:set(new_total)
  3377      Balances[from] = Balances[from] - bvalue - bfee
  3378      Balances[system.getOrigin()] = (Balances[system.getOrigin()] or b0) + bfee
  3379      Nonces[from] = Nonces[from] + 1
  3380      -- TODO event notification
  3381      return true
  3382  end
  3383  
  3384  
  3385  -- register functions to abi
  3386  abi.register(transfer, signed_transfer, mint, burn, signed_burn, hello)
  3387  	]]
  3388  	addr = contract.deploy(hello)
  3389  	ret = contract.call(addr, "hello", "world")
  3390  	return addr, ret
  3391  end
  3392  
  3393  function helloQuery(addr)
  3394  	return contract.call(addr, "hello", "world")
  3395  end
  3396  
  3397  function testConst()
  3398  	src = [[
  3399  		function hello(say, key) 
  3400  			return "Hello " .. say .. system.getItem(key) 
  3401  		end 
  3402  		function constructor(key, item) 
  3403  			system.setItem(key, item)
  3404  			return key, item
  3405  		end 
  3406  		abi.register(hello) 
  3407  		abi.payable(constructor)
  3408  	]]
  3409  	addr, key, item = contract.deploy.value(100)(src, "key", 2)
  3410  	ret = contract.call(addr, "hello", "world", "key")
  3411  	return addr, ret
  3412  end
  3413  
  3414  function testFail()
  3415  	src = [[
  3416  		function hello(say, key) 
  3417  			return "Hello " .. say .. system.getItem(key) 
  3418  		end 
  3419  		function constructor()
  3420  		end 
  3421  		abi.register(hello) 
  3422  	]]
  3423  	addr = contract.deploy.value(100)(src)
  3424  	return addr
  3425  end
  3426   
  3427  paddr = nil
  3428  function deploy()
  3429  	src = [[
  3430  		function hello(say, key) 
  3431  			return "Hello " .. say .. system.getItem(key) 
  3432  		end 
  3433  		function getcre()
  3434  			return system.getCreator()
  3435  		end
  3436  		function constructor()
  3437  		end 
  3438  		abi.register(hello, getcre) 
  3439  	]]
  3440  	paddr = contract.deploy(src)
  3441  	system.print("addr :", paddr)
  3442  	ret = contract.call(paddr, "hello", "world", "key")
  3443  end
  3444  
  3445  function testPcall()
  3446  	ret = contract.pcall(deploy)
  3447  	return contract.call(paddr, "getcre")
  3448  end
  3449  function constructor()
  3450  end
  3451  
  3452  abi.register(hello, helloQuery, testConst, testFail, testPcall)
  3453  abi.payable(constructor)
  3454  `
  3455  	bc, err := LoadDummyChain()
  3456  	if err != nil {
  3457  		t.Errorf("failed to create test database: %v", err)
  3458  	}
  3459  	defer bc.Release()
  3460  
  3461  	err = bc.ConnectBlock(
  3462  		NewLuaTxAccount("ktlee", 1000000000000),
  3463  		NewLuaTxDef("ktlee", "deploy", 50000000000, deploy),
  3464  	)
  3465  	if err != nil {
  3466  		t.Error(err)
  3467  	}
  3468  	tx := NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"hello"}`)
  3469  	err = bc.ConnectBlock(tx)
  3470  	if err != nil {
  3471  		t.Error(err)
  3472  	}
  3473  	receipt := bc.getReceipt(tx.hash())
  3474  	if receipt.GetRet() != `["AmgKtCaGjH4XkXwny2Jb1YH5gdsJGJh78ibWEgLmRWBS5LMfQuTf","Hello world"]` {
  3475  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  3476  	}
  3477  	err = bc.Query("deploy", `{"Name":"helloQuery", "Args":["AmgKtCaGjH4XkXwny2Jb1YH5gdsJGJh78ibWEgLmRWBS5LMfQuTf"]}`, "", `"Hello world"`)
  3478  	if err != nil {
  3479  		t.Error(err)
  3480  	}
  3481  	tx = NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"testConst"}`)
  3482  	err = bc.ConnectBlock(tx)
  3483  	receipt = bc.getReceipt(tx.hash())
  3484  	if receipt.GetRet() != `["Amhmj6kKZz7mPstBAPJWRe1e8RHP7bZ5pV35XatqTHMWeAVSyMkc","Hello world2"]` {
  3485  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  3486  	}
  3487  	deployAcc, err := bc.GetAccountState("deploy")
  3488  	if err != nil {
  3489  		t.Error(err)
  3490  	}
  3491  	if deployAcc.GetBalanceBigInt().Uint64() != uint64(49999999900) {
  3492  		t.Error(deployAcc.GetBalanceBigInt().Uint64())
  3493  	}
  3494  	tx = NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"testFail"}`)
  3495  	err = bc.ConnectBlock(tx)
  3496  	deployAcc, err = bc.GetAccountState("deploy")
  3497  	if err != nil && deployAcc.Nonce == 2 {
  3498  		t.Error(err)
  3499  	}
  3500  	tx = NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"testPcall"}`)
  3501  	err = bc.ConnectBlock(tx)
  3502  	deployAcc, err = bc.GetAccountState("deploy")
  3503  	if err != nil && deployAcc.Nonce == 2 {
  3504  		t.Error(err)
  3505  	}
  3506  	receipt = bc.getReceipt(tx.hash())
  3507  	if receipt.GetRet() != `` {
  3508  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  3509  	}
  3510  }
  3511  
  3512  func TestSqlVmPubNet(t *testing.T) {
  3513  	flushLState := func() {
  3514  		for i := 0; i <= MAX_LSTATE_SIZE; i++ {
  3515  			s := GetLState()
  3516  			FreeLState(s)
  3517  		}
  3518  	}
  3519  	PubNet = true
  3520  	flushLState()
  3521  	defer func() {
  3522  		PubNet = false
  3523  		flushLState()
  3524  	}()
  3525  
  3526  	bc, err := LoadDummyChain()
  3527  	if err != nil {
  3528  		t.Errorf("failed to create test database: %v", err)
  3529  	}
  3530  	defer bc.Release()
  3531  
  3532  	definition := `
  3533  function createAndInsert()
  3534      db.exec("create table if not exists dual(dummy char(1))")
  3535  	db.exec("insert into dual values ('X')")
  3536      local insertYZ = db.prepare("insert into dual values (?),(?)")
  3537      insertYZ:exec("Y", "Z")
  3538  end
  3539  abi.register(createAndInsert)`
  3540  
  3541  	err = bc.ConnectBlock(
  3542  		NewLuaTxAccount("ktlee", 100),
  3543  		NewLuaTxDef("ktlee", "simple-query", 0, definition),
  3544  	)
  3545  	if err != nil {
  3546  		t.Error(err)
  3547  	}
  3548  
  3549  	err = bc.ConnectBlock(
  3550  		NewLuaTxCall("ktlee", "simple-query", 0, `{"Name": "createAndInsert", "Args":[]}`).Fail(`attempt to index global 'db'`),
  3551  	)
  3552  	if err != nil {
  3553  		t.Error(err)
  3554  	}
  3555  }
  3556  
  3557  func TestReturnUData(t *testing.T) {
  3558  	bc, err := LoadDummyChain()
  3559  	if err != nil {
  3560  		t.Errorf("failed to create test database: %v", err)
  3561  	}
  3562  	defer bc.Release()
  3563  
  3564  	definition := `
  3565  	function test_die()
  3566  	return contract.call(system.getContractID(), "return_object")
  3567  	end
  3568  	function return_object()
  3569  	return db.query("select 1")
  3570  	end
  3571  	abi.register(test_die, return_object)`
  3572  
  3573  	err = bc.ConnectBlock(
  3574  		NewLuaTxAccount("ktlee", 100),
  3575  		NewLuaTxDef("ktlee", "rs-return", 0, definition),
  3576  	)
  3577  	if err != nil {
  3578  		t.Error(err)
  3579  	}
  3580  
  3581  	err = bc.ConnectBlock(
  3582  		NewLuaTxCall("ktlee", "rs-return", 0, `{"Name": "test_die", "Args":[]}`).Fail(`unsupport type: userdata`),
  3583  	)
  3584  	if err != nil {
  3585  		t.Error(err)
  3586  	}
  3587  }
  3588  
  3589  func checkRandomIntValue(v string, min, max int) error {
  3590  	n, _ := strconv.Atoi(v)
  3591  	if n < min || n > max {
  3592  		return errors.New("out of range")
  3593  	}
  3594  	return nil
  3595  }
  3596  
  3597  func TestRandom(t *testing.T) {
  3598  	bc, err := LoadDummyChain()
  3599  	if err != nil {
  3600  		t.Errorf("failed to create test database: %v", err)
  3601  	}
  3602  	defer bc.Release()
  3603  
  3604  	random := `
  3605  function random(...)
  3606  	return system.random(...)
  3607  end
  3608  abi.register(random)`
  3609  
  3610  	err = bc.ConnectBlock(
  3611  		NewLuaTxAccount("ktlee", 100),
  3612  		NewLuaTxDef("ktlee", "random", 0, random),
  3613  	)
  3614  	if err != nil {
  3615  		t.Error(err)
  3616  	}
  3617  	err = bc.ConnectBlock(
  3618  		NewLuaTxCall("ktlee", "random", 0, `{"Name": "random", "Args":[]}`).Fail(
  3619  			"1 or 2 arguments required",
  3620  		),
  3621  	)
  3622  	if err != nil {
  3623  		t.Error(err)
  3624  	}
  3625  
  3626  	err = bc.ConnectBlock(
  3627  		NewLuaTxCall(
  3628  			"ktlee",
  3629  			"random",
  3630  			0,
  3631  			`{"Name": "random", "Args":[0]}`).Fail("the maximum value must be greater than zero"),
  3632  	)
  3633  	if err != nil {
  3634  		t.Error(err)
  3635  	}
  3636  
  3637  	tx := NewLuaTxCall("ktlee", "random", 0, `{"Name": "random", "Args":[3]}`)
  3638  	err = bc.ConnectBlock(tx)
  3639  	if err != nil {
  3640  		t.Error(err)
  3641  	}
  3642  	receipt := bc.getReceipt(tx.hash())
  3643  	err = checkRandomIntValue(receipt.GetRet(), 1, 3)
  3644  	if err != nil {
  3645  		t.Errorf("error: %s, return value: %s", err.Error(), receipt.GetRet())
  3646  	}
  3647  
  3648  	tx = NewLuaTxCall("ktlee", "random", 0, `{"Name": "random", "Args":[3, 10]}`)
  3649  	err = bc.ConnectBlock(tx)
  3650  	receipt = bc.getReceipt(tx.hash())
  3651  	err = checkRandomIntValue(receipt.GetRet(), 3, 10)
  3652  	if err != nil {
  3653  		t.Errorf("error: %s, return value: %s", err.Error(), receipt.GetRet())
  3654  	}
  3655  
  3656  	err = bc.Query("random", `{"Name": "random", "Args":[1]}`, "", "1")
  3657  	if err != nil {
  3658  		t.Error(err)
  3659  	}
  3660  	err = bc.Query("random", `{"Name": "random", "Args":[4,4]}`, "", "4")
  3661  	if err != nil {
  3662  		t.Error(err)
  3663  	}
  3664  	err = bc.Query("random", `{"Name": "random", "Args":[0,4]}`, "system.random: the minimum value must be greater than zero", "")
  3665  	if err != nil {
  3666  		t.Error(err)
  3667  	}
  3668  	err = bc.Query("random", `{"Name": "random", "Args":[3,1]}`, "system.random: the maximum value must be greater than the minimum value", "")
  3669  	if err != nil {
  3670  		t.Error(err)
  3671  	}
  3672  }
  3673  
  3674  func TestBigTable(t *testing.T) {
  3675  	bc, err := LoadDummyChain()
  3676  	if err != nil {
  3677  		t.Errorf("failed to create test database: %v", err)
  3678  	}
  3679  	defer bc.Release()
  3680  
  3681  	bigSrc := `
  3682  function constructor()
  3683      db.exec("create table if not exists table1 (cid integer PRIMARY KEY, rgtime datetime)")
  3684      db.exec("insert into table1 (rgtime) values (datetime('2018-10-30 16:00:00'))")
  3685  end
  3686  
  3687  function inserts(n)
  3688      for i = 1, n do
  3689          db.exec("insert into table1 (rgtime) select rgtime from table1")
  3690      end
  3691  end
  3692  
  3693  abi.register(inserts)
  3694  `
  3695  
  3696  	err = bc.ConnectBlock(
  3697  		NewLuaTxAccount("ktlee", 100),
  3698  		NewLuaTxDef("ktlee", "big", 0, bigSrc),
  3699  	)
  3700  	if err != nil {
  3701  		t.Error(err)
  3702  	}
  3703  
  3704  	// About 900MB
  3705  	err = bc.ConnectBlock(
  3706  		NewLuaTxCall("ktlee", "big", 0, `{"Name": "inserts", "Args":[25]}`),
  3707  	)
  3708  	if err != nil {
  3709  		t.Error(err)
  3710  	}
  3711  
  3712  	SetStateSQLMaxDBSize(20)
  3713  
  3714  	bigSrc = `
  3715  function constructor()
  3716      db.exec("create table if not exists aergojdbc001 (name text, yyyymmdd text)")
  3717      db.exec("insert into aergojdbc001 values ('홍길동', '20191007')")
  3718      db.exec("insert into aergojdbc001 values ('홍길동', '20191007')")
  3719      db.exec("insert into aergojdbc001 values ('홍길동', '20191007')")
  3720  end
  3721  
  3722  function inserts()
  3723  	db.exec("insert into aergojdbc001 select * from aergojdbc001")
  3724  end
  3725  
  3726  abi.register(inserts)
  3727  `
  3728  
  3729  	err = bc.ConnectBlock(
  3730  		NewLuaTxAccount("ktlee", 100),
  3731  		NewLuaTxDef("ktlee", "big20", 0, bigSrc),
  3732  	)
  3733  	if err != nil {
  3734  		t.Error(err)
  3735  	}
  3736  
  3737  	for i := 0; i < 17; i++ {
  3738  		err = bc.ConnectBlock(
  3739  			NewLuaTxCall("ktlee", "big20", 0, `{"Name": "inserts"}`),
  3740  		)
  3741  		if err != nil {
  3742  			t.Error(err)
  3743  		}
  3744  	}
  3745  	err = bc.ConnectBlock(
  3746  		NewLuaTxCall("ktlee", "big20", 0, `{"Name": "inserts"}`).Fail("database or disk is full"),
  3747  	)
  3748  	if err != nil {
  3749  		t.Error(err)
  3750  	}
  3751  }
  3752  
  3753  func TestEvent(t *testing.T) {
  3754  	bc, err := LoadDummyChain()
  3755  	if err != nil {
  3756  		t.Errorf("failed to create test database: %v", err)
  3757  	}
  3758  	defer bc.Release()
  3759  
  3760  	definition := `
  3761      function test_ev()
  3762          contract.event("ev1", 1,"local", 2, "form")
  3763          contract.event("ev1", 3,"local", 4, "form")
  3764      end
  3765      abi.register(test_ev)`
  3766  
  3767  	err = bc.ConnectBlock(
  3768  		NewLuaTxAccount("ktlee", 100),
  3769  		NewLuaTxDef("ktlee", "event", 0, definition),
  3770  	)
  3771  	if err != nil {
  3772  		t.Error(err)
  3773  	}
  3774  	err = bc.ConnectBlock(
  3775  		NewLuaTxCall("ktlee", "event", 0, `{"Name": "test_ev", "Args":[]}`),
  3776  	)
  3777  	if err != nil {
  3778  		t.Error(err)
  3779  	}
  3780  }
  3781  
  3782  func TestView(t *testing.T) {
  3783  	bc, err := LoadDummyChain()
  3784  	if err != nil {
  3785  		t.Errorf("failed to create test database: %v", err)
  3786  	}
  3787  	defer bc.Release()
  3788  
  3789  	definition := `
  3790      function test_view()
  3791          contract.event("ev1", 1,"local", 2, "form")
  3792          contract.event("ev1", 3,"local", 4, "form")
  3793      end
  3794  	function k()
  3795  		return 10
  3796  	end
  3797  	function tx_in_view_function()
  3798  		k2()
  3799  	end
  3800  	function k2()
  3801  		test_view()
  3802  	end
  3803  	function tx_after_view_function()
  3804  		k()
  3805          contract.event("ev1", 1,"local", 2, "form")
  3806  	end
  3807      abi.register(test_view, tx_after_view_function)
  3808      abi.register_view(test_view, k, tx_in_view_function)
  3809  `
  3810  
  3811  	err = bc.ConnectBlock(
  3812  		NewLuaTxAccount("ktlee", 100),
  3813  		NewLuaTxDef("ktlee", "view", 0, definition),
  3814  	)
  3815  	if err != nil {
  3816  		t.Error(err)
  3817  	}
  3818  	err = bc.ConnectBlock(
  3819  		NewLuaTxCall("ktlee", "view", 0, `{"Name": "test_view", "Args":[]}`).Fail("[Contract.Event] event not permitted in query"),
  3820  	)
  3821  	if err != nil {
  3822  		t.Error(err)
  3823  	}
  3824  	err = bc.Query("view", `{"Name":"k", "Args":[]}`, "", "10")
  3825  	if err != nil {
  3826  		t.Error(err)
  3827  	}
  3828  	err = bc.ConnectBlock(
  3829  		NewLuaTxCall("ktlee", "view", 0, `{"Name": "tx_in_view_function", "Args":[]}`).Fail("[Contract.Event] event not permitted in query"),
  3830  	)
  3831  	if err != nil {
  3832  		t.Error(err)
  3833  	}
  3834  	err = bc.ConnectBlock(
  3835  		NewLuaTxCall("ktlee", "view", 0, `{"Name": "tx_after_view_function", "Args":[]}`),
  3836  	)
  3837  	if err != nil {
  3838  		t.Error(err)
  3839  	}
  3840  }
  3841  
  3842  func TestNsec(t *testing.T) {
  3843  	bc, err := LoadDummyChain()
  3844  	if err != nil {
  3845  		t.Errorf("failed to create test database: %v", err)
  3846  	}
  3847  	defer bc.Release()
  3848  
  3849  	definition := `
  3850  	function test_nsec()
  3851  		system.print(nsec())
  3852  	end
  3853  	abi.register(test_nsec)`
  3854  
  3855  	err = bc.ConnectBlock(
  3856  		NewLuaTxAccount("ktlee", 100),
  3857  		NewLuaTxDef("ktlee", "nsec", 0, definition),
  3858  	)
  3859  	err = bc.ConnectBlock(
  3860  		NewLuaTxCall("ktlee", "nsec", 0, `{"Name": "test_nsec"}`).Fail(`attempt to call global 'nsec' (a nil value)`),
  3861  	)
  3862  	if err != nil {
  3863  		t.Error(err)
  3864  	}
  3865  }
  3866  
  3867  func TestGovernance(t *testing.T) {
  3868  	bc, err := LoadDummyChain()
  3869  	if err != nil {
  3870  		t.Errorf("failed to create test database: %v", err)
  3871  	}
  3872  	defer bc.Release()
  3873  
  3874  	definition := `
  3875      function test_gov()
  3876  		contract.stake("10000 aergo")
  3877  		contract.vote("16Uiu2HAm2gtByd6DQu95jXURJXnS59Dyb9zTe16rDrcwKQaxma4p")
  3878      end
  3879  
  3880  	function error_case()
  3881  		contract.stake("10000 aergo")
  3882  		assert(false)
  3883  	end
  3884  	
  3885  	function test_pcall()
  3886  		return contract.pcall(error_case)
  3887  	end
  3888  		
  3889      abi.register(test_gov, test_pcall, error_case)
  3890  	abi.payable(test_gov, test_pcall)
  3891  `
  3892  
  3893  	err = bc.ConnectBlock(
  3894  		NewLuaTxAccount("ktlee", 100),
  3895  		NewLuaTxDef("ktlee", "gov", 0, definition),
  3896  	)
  3897  	if err != nil {
  3898  		t.Error(err)
  3899  	}
  3900  	amount, _ := new(big.Int).SetString("10000000000000000000000", 10)
  3901  	err = bc.ConnectBlock(
  3902  		NewLuaTxCallBig("ktlee", "gov", amount, `{"Name": "test_gov", "Args":[]}`),
  3903  	)
  3904  	if err != nil {
  3905  		t.Error(err)
  3906  	}
  3907  	oldstaking, err := bc.GetStaking("gov")
  3908  	if err != nil {
  3909  		t.Error(err)
  3910  	}
  3911  	oldgov, err := bc.GetAccountState("gov")
  3912  	if err != nil {
  3913  		t.Error(err)
  3914  	}
  3915  	tx := NewLuaTxCall("ktlee", "gov", 0, `{"Name": "test_pcall", "Args":[]}`)
  3916  	err = bc.ConnectBlock(tx)
  3917  	if err != nil {
  3918  		t.Error(err)
  3919  	}
  3920  	staking, err := bc.GetStaking("gov")
  3921  	if err != nil {
  3922  		t.Error(err)
  3923  	}
  3924  	gov, err := bc.GetAccountState("gov")
  3925  	if err != nil {
  3926  		t.Error(err)
  3927  	}
  3928  
  3929  	if bytes.Equal(oldstaking.Amount, staking.Amount) == false ||
  3930  		bytes.Equal(oldgov.GetBalance(), gov.GetBalance()) == false {
  3931  		t.Error("pcall error")
  3932  	}
  3933  	tx = NewLuaTxCall("ktlee", "gov", 0, `{"Name": "error_case", "Args":[]}`)
  3934  	_ = bc.ConnectBlock(tx)
  3935  	newstaking, err := bc.GetStaking("gov")
  3936  	if err != nil {
  3937  		t.Error(err)
  3938  	}
  3939  	newgov, err := bc.GetAccountState("gov")
  3940  	if err != nil {
  3941  		t.Error(err)
  3942  	}
  3943  	if bytes.Equal(oldstaking.Amount, newstaking.Amount) == false ||
  3944  		bytes.Equal(oldgov.GetBalance(), newgov.GetBalance()) == false {
  3945  		fmt.Println(new(big.Int).SetBytes(newstaking.Amount).String(), newgov.GetBalanceBigInt().String())
  3946  		t.Error("pcall error")
  3947  	}
  3948  }
  3949  
  3950  func TestContractSend(t *testing.T) {
  3951  	bc, err := LoadDummyChain()
  3952  	if err != nil {
  3953  		t.Errorf("failed to create test database: %v", err)
  3954  	}
  3955  	defer bc.Release()
  3956  
  3957  	definition := `
  3958  	function constructor()
  3959  	end
  3960      function send(addr)
  3961          contract.send(addr,1)
  3962      end
  3963      abi.register(send, constructor)
  3964  	abi.payable(constructor)
  3965  `
  3966  	definition2 := `
  3967      function default()
  3968  		system.print("default called")
  3969      end
  3970      abi.register(default)
  3971  	abi.payable(default)
  3972  `
  3973  	definition3 := `
  3974      function test()
  3975      end
  3976      abi.register(test)
  3977  `
  3978  	definition4 := `
  3979      function default()
  3980      end
  3981      abi.register(default)
  3982  `
  3983  	err = bc.ConnectBlock(
  3984  		NewLuaTxAccount("ktlee", 100),
  3985  		NewLuaTxDef("ktlee", "test1", 50, definition),
  3986  		NewLuaTxDef("ktlee", "test2", 0, definition2),
  3987  		NewLuaTxDef("ktlee", "test3", 0, definition3),
  3988  		NewLuaTxDef("ktlee", "test4", 0, definition4),
  3989  	)
  3990  	if err != nil {
  3991  		t.Error(err)
  3992  	}
  3993  	err = bc.ConnectBlock(
  3994  		NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("test2")))),
  3995  	)
  3996  	if err != nil {
  3997  		t.Error(err)
  3998  	}
  3999  	err = bc.ConnectBlock(
  4000  		NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("test3")))).Fail(`[Contract.LuaSendAmount] newExecutor error: not found function: default`),
  4001  	)
  4002  	if err != nil {
  4003  		t.Error(err)
  4004  	}
  4005  	err = bc.ConnectBlock(
  4006  		NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("test4")))).Fail(`[Contract.LuaSendAmount] newExecutor error: 'default' is not payable`),
  4007  	)
  4008  	if err != nil {
  4009  		t.Error(err)
  4010  	}
  4011  
  4012  	err = bc.ConnectBlock(
  4013  		NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("ktlee")))),
  4014  	)
  4015  	if err != nil {
  4016  		t.Error(err)
  4017  	}
  4018  }
  4019  
  4020  func TestMaxMemSize(t *testing.T) {
  4021  	bc, err := LoadDummyChain()
  4022  	if err != nil {
  4023  		t.Errorf("failed to create test database: %v", err)
  4024  	}
  4025  	defer bc.Release()
  4026  
  4027  	definition := `
  4028  function oom()
  4029  	 local s = "hello"
  4030  
  4031  	 while 1 do
  4032  		 s = s .. s
  4033  	 end
  4034  end
  4035  
  4036  function p()
  4037  	pcall(oom)
  4038  end
  4039  
  4040  function cp()
  4041  	contract.pcall(oom)
  4042  end
  4043  abi.register(oom, p, cp)`
  4044  
  4045  	err = bc.ConnectBlock(
  4046  		NewLuaTxAccount("ktlee", 100),
  4047  		NewLuaTxDef("ktlee", "oom", 0, definition),
  4048  	)
  4049  	err = bc.ConnectBlock(
  4050  		NewLuaTxCall(
  4051  			"ktlee",
  4052  			"oom",
  4053  			0,
  4054  			`{"Name":"oom"}`,
  4055  		),
  4056  	)
  4057  	errMsg := "not enough memory"
  4058  	if err == nil {
  4059  		t.Errorf("expected: %s", errMsg)
  4060  	}
  4061  	if err != nil && !strings.Contains(err.Error(), errMsg) {
  4062  		t.Error(err)
  4063  	}
  4064  	err = bc.ConnectBlock(
  4065  		NewLuaTxCall(
  4066  			"ktlee",
  4067  			"oom",
  4068  			0,
  4069  			`{"Name":"p"}`,
  4070  		).Fail(errMsg),
  4071  	)
  4072  	if err != nil {
  4073  		t.Error(err)
  4074  	}
  4075  	err = bc.ConnectBlock(
  4076  		NewLuaTxCall(
  4077  			"ktlee",
  4078  			"oom",
  4079  			0,
  4080  			`{"Name":"cp"}`,
  4081  		).Fail(errMsg),
  4082  	)
  4083  	if err != nil {
  4084  		t.Error(err)
  4085  	}
  4086  }
  4087  
  4088  func TestDeploy2(t *testing.T) {
  4089  	deploy := `
  4090  function hello()
  4091  	src = [[
  4092  state.var{
  4093    counts = state.array(10)
  4094  }
  4095  
  4096  counts[1] = 10
  4097  function inc(key)
  4098    if counts[key] == nil then
  4099      counts[key] = 0
  4100    end
  4101    counts[key] = counts[key] + 1
  4102  end
  4103  
  4104  function get(key)
  4105    return counts[key]
  4106  end
  4107  
  4108  function set(key,val)
  4109    counts[key] = val
  4110  end
  4111  
  4112  function len()
  4113    return counts:length()
  4114  end
  4115  
  4116  function iter()
  4117    local rv = {}
  4118    for i, v in counts:ipairs() do
  4119      if v == nil then
  4120        rv[i] = "nil"
  4121      else
  4122        rv[i] = v
  4123      end
  4124    end
  4125    return rv
  4126  end
  4127  
  4128  abi.register(inc,get,set,len,iter)
  4129  	]]
  4130  	paddr = contract.deploy(src)
  4131  	system.print("addr :", paddr)
  4132  	ret = contract.call(paddr, "hello", "world", "key")
  4133  end
  4134  
  4135  function constructor()
  4136  end
  4137  
  4138  abi.register(hello)
  4139  abi.payable(constructor)
  4140  `
  4141  	bc, err := LoadDummyChain()
  4142  	if err != nil {
  4143  		t.Errorf("failed to create test database: %v", err)
  4144  	}
  4145  	defer bc.Release()
  4146  
  4147  	err = bc.ConnectBlock(
  4148  		NewLuaTxAccount("ktlee", 1000000000000),
  4149  		NewLuaTxDef("ktlee", "deploy", 50000000000, deploy),
  4150  	)
  4151  	if err != nil {
  4152  		t.Error(err)
  4153  	}
  4154  	tx := NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"hello"}`).Fail(`[Contract.LuaDeployContract]newExecutor Error :not permitted state referencing at global scope`)
  4155  	err = bc.ConnectBlock(tx)
  4156  	if err != nil {
  4157  		t.Error(err)
  4158  	}
  4159  }
  4160  
  4161  func TestInvalidKey(t *testing.T) {
  4162  	src := `
  4163  state.var {
  4164  	h = state.map(),
  4165  	arr = state.array(10),
  4166  	v = state.value()
  4167  }
  4168  
  4169  t = {}
  4170  
  4171  function key_table()
  4172  	local k = {}
  4173  	t[k] = "table"
  4174  end
  4175  
  4176  function key_func()
  4177  	t[key_table] = "function"
  4178  end
  4179  
  4180  function key_statemap(key)
  4181  	t[h] = "state.map"
  4182  end
  4183  
  4184  function key_statearray(key)
  4185  	t[arr] = "state.array"
  4186  end
  4187  
  4188  function key_statevalue(key)
  4189  	t[v] = "state.value"
  4190  end
  4191  
  4192  function key_upval(key)
  4193  	local k = {}
  4194  	local f = function()
  4195  		t[k] = "upval"
  4196  	end
  4197  	f()
  4198  end
  4199  
  4200  function key_nil(key)
  4201  	h[nil] = "nil"
  4202  end
  4203  
  4204  abi.register(key_table, key_func, key_statemap, key_statearray, key_statevalue, key_upval, key_nil)
  4205  `
  4206  	bc, err := LoadDummyChain()
  4207  	if err != nil {
  4208  		t.Errorf("failed to create test database: %v", err)
  4209  	}
  4210  	defer bc.Release()
  4211  
  4212  	err = bc.ConnectBlock(
  4213  		NewLuaTxAccount("ktlee", 100),
  4214  		NewLuaTxDef("ktlee", "invalidkey", 0, src),
  4215  	)
  4216  	if err != nil {
  4217  		t.Error(err)
  4218  	}
  4219  
  4220  	err = bc.ConnectBlock(
  4221  		NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_table"}`).Fail(
  4222  			"cannot use 'table' as a key",
  4223  		),
  4224  	)
  4225  	if err != nil {
  4226  		t.Error(err)
  4227  	}
  4228  	err = bc.ConnectBlock(
  4229  		NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_func"}`).Fail(
  4230  			"cannot use 'function' as a key",
  4231  		),
  4232  	)
  4233  	if err != nil {
  4234  		t.Error(err)
  4235  	}
  4236  	err = bc.ConnectBlock(
  4237  		NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_statemap"}`).Fail(
  4238  			"cannot use 'userdata' as a key",
  4239  		),
  4240  	)
  4241  	if err != nil {
  4242  		t.Error(err)
  4243  	}
  4244  	err = bc.ConnectBlock(
  4245  		NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_statearray"}`).Fail(
  4246  			"cannot use 'userdata' as a key",
  4247  		),
  4248  	)
  4249  	if err != nil {
  4250  		t.Error(err)
  4251  	}
  4252  	err = bc.ConnectBlock(
  4253  		NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_statevalue"}`).Fail(
  4254  			"cannot use 'userdata' as a key",
  4255  		),
  4256  	)
  4257  	if err != nil {
  4258  		t.Error(err)
  4259  	}
  4260  	err = bc.ConnectBlock(
  4261  		NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_upval"}`).Fail(
  4262  			"cannot use 'table' as a key",
  4263  		),
  4264  	)
  4265  	if err != nil {
  4266  		t.Error(err)
  4267  	}
  4268  	err = bc.ConnectBlock(
  4269  		NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_nil"}`).Fail(
  4270  			"invalid key type: 'nil', state.map: 'h'",
  4271  		),
  4272  	)
  4273  	if err != nil {
  4274  		t.Error(err)
  4275  	}
  4276  }
  4277  
  4278  func TestPcallRollback(t *testing.T) {
  4279  	definition1 := `
  4280  	function constructor(init)
  4281  		system.setItem("count", init)
  4282  	end
  4283  
  4284  	function init()
  4285  		db.exec([[create table if not exists r (
  4286  	  id integer primary key
  4287  	, n integer check(n >= 10)
  4288  	, nonull text not null
  4289  	, only integer unique)
  4290  	]])
  4291  		db.exec("insert into r values (1, 11, 'text', 1)")
  4292  	end
  4293  
  4294  	function pkins1()
  4295  		db.exec("insert into r values (3, 12, 'text', 2)")
  4296  		db.exec("insert into r values (1, 12, 'text', 2)")
  4297  	end
  4298  
  4299  	function pkins2()
  4300  		db.exec("insert into r values (4, 12, 'text', 2)")
  4301  	end
  4302  
  4303  	function pkget()
  4304  		local rs = db.query("select count(*) from r")
  4305  		if rs:next() then
  4306  			local n = rs:get()
  4307  			--rs:next()
  4308  			return n
  4309  		else
  4310  			return "error in count()"
  4311  		end
  4312  	end
  4313  
  4314  	function inc()
  4315  		count = system.getItem("count")
  4316  		system.setItem("count", count + 1)
  4317  		return count
  4318  	end
  4319  
  4320  	function get()
  4321  		return system.getItem("count")
  4322  	end
  4323  
  4324  	function getOrigin()
  4325  		return system.getOrigin()
  4326  	end
  4327  
  4328  	function set(val)
  4329  		system.setItem("count", val)
  4330  	end
  4331  	abi.register(inc,get,set, init, pkins1, pkins2, pkget, getOrigin)
  4332  	abi.payable(constructor, inc)
  4333  	`
  4334  
  4335  	bc, err := LoadDummyChain()
  4336  	if err != nil {
  4337  		t.Errorf("failed to create test database: %v", err)
  4338  	}
  4339  	defer bc.Release()
  4340  
  4341  	err = bc.ConnectBlock(
  4342  		NewLuaTxAccount("ktlee", 100),
  4343  		NewLuaTxDef("ktlee", "counter", 10, definition1).Constructor("[0]"),
  4344  		NewLuaTxCall("ktlee", "counter", 15, `{"Name":"inc", "Args":[]}`),
  4345  	)
  4346  
  4347  	err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1")
  4348  	if err != nil {
  4349  		t.Error(err)
  4350  	}
  4351  
  4352  	definition2 := `
  4353  	function constructor(addr)
  4354  		system.setItem("count", 99)
  4355  		system.setItem("addr", addr)
  4356  	end
  4357  	function add(amount)
  4358  		first = contract.call.value(amount)(system.getItem("addr"), "inc")
  4359  		status, res = pcall(contract.call.value(1000000), system.getItem("addr"), "inc")
  4360  		if status == false then
  4361  			return first
  4362  		end
  4363  		return res
  4364  	end
  4365  	function dadd()
  4366  		return contract.delegatecall(system.getItem("addr"), "inc")
  4367  	end
  4368  	function get()
  4369  		addr = system.getItem("addr")
  4370  		a = contract.call(addr, "get")
  4371  		return a
  4372  	end
  4373  	function dget()
  4374  		addr = system.getItem("addr")
  4375  		a = contract.delegatecall(addr, "get")
  4376  		return a
  4377  	end
  4378  	function send(addr, amount)
  4379  		contract.send(addr, amount)
  4380  		status, res = pcall(contract.call.value(1000000000)(system.getItem("addr"), "inc"))
  4381  		return status
  4382  	end
  4383  	function sql()
  4384  		contract.call(system.getItem("addr"), "init")
  4385  		pcall(contract.call, system.getItem("addr"), "pkins1")
  4386  		contract.call(system.getItem("addr"), "pkins2")
  4387  		return status
  4388  	end
  4389  
  4390  	function sqlget()
  4391  		return contract.call(system.getItem("addr"), "pkget")
  4392  	end
  4393  
  4394  	function getOrigin()
  4395  		return contract.call(system.getItem("addr"), "getOrigin")
  4396  	end
  4397  	abi.register(add, dadd, get, dget, send, sql, sqlget, getOrigin)
  4398  	abi.payable(constructor,add)
  4399  	`
  4400  	err = bc.ConnectBlock(
  4401  		NewLuaTxDef("ktlee", "caller", 10, definition2).
  4402  			Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("counter")))),
  4403  		NewLuaTxCall("ktlee", "caller", 15, `{"Name":"add", "Args":[]}`),
  4404  	)
  4405  	if err != nil {
  4406  		t.Error(err)
  4407  	}
  4408  
  4409  	err = bc.ConnectBlock(
  4410  		NewLuaTxCall("ktlee", "caller", 0, `{"Name":"sql", "Args":[]}`),
  4411  	)
  4412  	if err != nil {
  4413  		t.Error(err)
  4414  	}
  4415  	err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "2")
  4416  	if err != nil {
  4417  		t.Error(err)
  4418  	}
  4419  	err = bc.Query("caller", `{"Name":"sqlget", "Args":[]}`, "", "2")
  4420  	if err != nil {
  4421  		t.Error(err)
  4422  	}
  4423  
  4424  	tx := NewLuaTxCall("ktlee", "caller", 0, `{"Name":"getOrigin", "Args":[]}`)
  4425  	_ = bc.ConnectBlock(tx)
  4426  	receipt := bc.getReceipt(tx.hash())
  4427  	if receipt.GetRet() != "\""+types.EncodeAddress(strHash("ktlee"))+"\"" {
  4428  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  4429  	}
  4430  
  4431  	definition3 := `
  4432  	function pass(addr)
  4433  		contract.send(addr, 1)
  4434  	end
  4435  
  4436  	function add(addr, a, b)
  4437  		system.setItem("arg", a)
  4438  		contract.pcall(pass, addr)
  4439  		return a+b
  4440  	end
  4441  
  4442  	function set(addr)
  4443  		contract.send(addr, 1)
  4444  		system.setItem("arg", 2)
  4445  		status, ret  = contract.pcall(add, addr, 1, 2)
  4446  	end
  4447  
  4448  	function set2(addr)
  4449  		contract.send(addr, 1)
  4450  		system.setItem("arg", 2)
  4451  		status, ret  = contract.pcall(add, addar, 1)
  4452  	end
  4453  
  4454  	function get()
  4455  		return system.getItem("arg")
  4456  	end
  4457  	
  4458  	function getBalance()
  4459  		return contract.balance()
  4460  	end
  4461  
  4462  	abi.register(set, set2, get, getBalance)
  4463  	abi.payable(set, set2)
  4464  	`
  4465  
  4466  	bc, err = LoadDummyChain()
  4467  	if err != nil {
  4468  		t.Errorf("failed to create test database: %v", err)
  4469  	}
  4470  	defer bc.Release()
  4471  
  4472  	err = bc.ConnectBlock(
  4473  		NewLuaTxAccount("ktlee", 100),
  4474  		NewLuaTxAccount("bong", 0),
  4475  		NewLuaTxDef("ktlee", "counter", 0, definition3),
  4476  	)
  4477  	if err != nil {
  4478  		t.Error(err)
  4479  	}
  4480  	tx = NewLuaTxCall("ktlee", "counter", 20,
  4481  		fmt.Sprintf(`{"Name":"set", "Args":["%s"]}`, types.EncodeAddress(strHash("bong"))))
  4482  	err = bc.ConnectBlock(tx)
  4483  	if err != nil {
  4484  		t.Error(err)
  4485  	}
  4486  	err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1")
  4487  	if err != nil {
  4488  		t.Error(err)
  4489  	}
  4490  	err = bc.Query("counter", `{"Name":"getBalance", "Args":[]}`, "", "\"18\"")
  4491  	if err != nil {
  4492  		t.Error(err)
  4493  	}
  4494  	state, err := bc.GetAccountState("bong")
  4495  	if state.GetBalanceBigInt().Uint64() != 2 {
  4496  		t.Error("balance error")
  4497  	}
  4498  	tx = NewLuaTxCall("ktlee", "counter", 10,
  4499  		fmt.Sprintf(`{"Name":"set2", "Args":["%s"]}`, types.EncodeAddress(strHash("bong"))))
  4500  	err = bc.ConnectBlock(tx)
  4501  	if err != nil {
  4502  		t.Error(err)
  4503  	}
  4504  	err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "2")
  4505  	if err != nil {
  4506  		t.Error(err)
  4507  	}
  4508  	state, err = bc.GetAccountState("bong")
  4509  	if state.GetBalanceBigInt().Uint64() != 3 {
  4510  		t.Error("balance error")
  4511  	}
  4512  }
  4513  
  4514  func TestNestedPcall(t *testing.T) {
  4515  	definition1 := `
  4516  state.var {
  4517      Map = state.map(),
  4518  }
  4519  function map(a)
  4520    return Map[a]
  4521  end
  4522  function constructor()
  4523  end
  4524  function pcall3(to)
  4525    contract.send(to, "1 aergo")
  4526  end
  4527  function pcall2(addr, to)
  4528    status = pcall(contract.call, addr, "pcall3", to)
  4529    system.print(status)
  4530    assert(false)
  4531  end
  4532  function pcall1(addr, to)
  4533    status = pcall(contract.call, addr, "pcall2", addr, to)
  4534    system.print(status)
  4535    Map[addr] = 2
  4536    status = pcall(contract.call, addr, "pcall3", to)
  4537    system.print(status)
  4538    status = pcall(contract.call, addr, "pcall2", addr, to)
  4539    system.print(status)
  4540  end
  4541  function default()
  4542  end
  4543  abi.register(map, pcall1, pcall2, pcall3, default)
  4544  abi.payable(pcall1, default, constructor)
  4545  	`
  4546  
  4547  	bc, err := LoadDummyChain()
  4548  	if err != nil {
  4549  		t.Errorf("failed to create test database: %v", err)
  4550  	}
  4551  	defer bc.Release()
  4552  
  4553  	err = bc.ConnectBlock(
  4554  		NewLuaTxAccount("ktlee", 100),
  4555  		NewLuaTxAccount("bong", 0),
  4556  		NewLuaTxDef("ktlee", "pcall", 10000000000000000000, definition1),
  4557  	)
  4558  	if err != nil {
  4559  		t.Error(err)
  4560  	}
  4561  	err = bc.ConnectBlock(
  4562  		NewLuaTxCall("ktlee", "pcall", 0,
  4563  			fmt.Sprintf(`{"Name":"pcall1", "Args":["%s", "%s"]}`,
  4564  				types.EncodeAddress(strHash("pcall")), types.EncodeAddress(strHash("bong")))),
  4565  	)
  4566  	if err != nil {
  4567  		t.Error(err)
  4568  	}
  4569  	err = bc.Query("pcall", fmt.Sprintf(`{"Name":"map", "Args":["%s"]}`,
  4570  		types.EncodeAddress(strHash("pcall"))), "", "2")
  4571  	if err != nil {
  4572  		t.Error(err)
  4573  	}
  4574  	state, err := bc.GetAccountState("bong")
  4575  	if state.GetBalanceBigInt().Uint64() != 1000000000000000000 {
  4576  		t.Error("balance error", state.GetBalanceBigInt().Uint64())
  4577  	}
  4578  }
  4579  
  4580  func TestSnapshot(t *testing.T) {
  4581  	bc, err := LoadDummyChain()
  4582  	if err != nil {
  4583  		t.Errorf("failed to create test database: %v", err)
  4584  	}
  4585  	defer bc.Release()
  4586  
  4587  	definition := `
  4588  	state.var{
  4589  		counts = state.map(),
  4590  		data = state.value(),
  4591  		array = state.array(10)
  4592  	}
  4593  
  4594  	function inc()
  4595  		a = system.getItem("key1")
  4596  		if (a == nil) then
  4597  			system.setItem("key1", 1)
  4598  			return
  4599  		end
  4600  		system.setItem("key1", a + 1)
  4601  		counts["key1"] = a + 1
  4602  		data:set(a+1)
  4603  		array[1] = a + 1
  4604  	end
  4605  	function query(a)
  4606  			return system.getItem("key1", a), state.getsnap(counts, "key1", a), state.getsnap(data,a), state.getsnap(array, 1, a)
  4607  	end
  4608  	function query2()
  4609  			return state.getsnap(array, 1)
  4610  	end
  4611  	abi.register(inc, query, query2)
  4612  	abi.payable(inc)`
  4613  
  4614  	err = bc.ConnectBlock(
  4615  		NewLuaTxAccount("ktlee", 100),
  4616  		NewLuaTxDef("ktlee", "snap", 0, definition),
  4617  	)
  4618  	if err != nil {
  4619  		t.Error(err)
  4620  	}
  4621  	err = bc.ConnectBlock(
  4622  		NewLuaTxCall("ktlee", "snap", 0, `{"Name": "inc", "Args":[]}`),
  4623  	)
  4624  	if err != nil {
  4625  		t.Error(err)
  4626  	}
  4627  	err = bc.ConnectBlock(
  4628  		NewLuaTxCall("ktlee", "snap", 0, `{"Name": "inc", "Args":[]}`),
  4629  	)
  4630  	if err != nil {
  4631  		t.Error(err)
  4632  	}
  4633  	err = bc.ConnectBlock(
  4634  		NewLuaTxCall("ktlee", "snap", 0, `{"Name": "inc", "Args":[]}`),
  4635  	)
  4636  	if err != nil {
  4637  		t.Error(err)
  4638  	}
  4639  	err = bc.Query("snap", `{"Name":"query"}`, "", "[3,3,3,3]")
  4640  	if err != nil {
  4641  		t.Error(err)
  4642  	}
  4643  	err = bc.Query("snap", `{"Name":"query", "Args":[2]}`, "", "[1,{},{},{}]")
  4644  	if err != nil {
  4645  		t.Error(err)
  4646  	}
  4647  	err = bc.Query("snap", `{"Name":"query", "Args":[3]}`, "", "[2,2,2,2]")
  4648  	if err != nil {
  4649  		t.Error(err)
  4650  	}
  4651  	err = bc.Query("snap", `{"Name":"query2", "Args":[]}`,
  4652  		"invalid argument at getsnap, need (state.array, index, blockheight)", "")
  4653  	if err != nil {
  4654  		t.Error(err)
  4655  	}
  4656  }
  4657  
  4658  func TestByteKey(t *testing.T) {
  4659  	bk := `
  4660  state.var {
  4661      c = state.map(),
  4662  }
  4663  
  4664  function constructor()
  4665      c[fromhex('00')] = "kk"
  4666      c[fromhex('61')] = "kk"
  4667      system.setItem(fromhex('00'), "kk")
  4668  end
  4669  
  4670  function fromhex(str)
  4671      return (str:gsub('..', function (cc)
  4672          return string.char(tonumber(cc, 16))
  4673      end))
  4674  end
  4675  function get()
  4676  	return c[fromhex('00')], system.getItem(fromhex('00')), system.getItem(fromhex('0000'))
  4677  end
  4678  function getcre()
  4679  	return system.getCreator()
  4680  end
  4681  abi.register(get, getcre)
  4682  `
  4683  	bc, err := LoadDummyChain()
  4684  	if err != nil {
  4685  		t.Errorf("failed to create test database: %v", err)
  4686  	}
  4687  	defer bc.Release()
  4688  
  4689  	err = bc.ConnectBlock(
  4690  		NewLuaTxAccount("ktlee", 100000),
  4691  		NewLuaTxDef("ktlee", "bk", 0, bk),
  4692  	)
  4693  	if err != nil {
  4694  		t.Error(err)
  4695  	}
  4696  	err = bc.Query("bk", `{"Name":"get"}`, "", `["kk","kk"]`)
  4697  	if err != nil {
  4698  		t.Error(err)
  4699  	}
  4700  	err = bc.Query("bk", `{"Name":"getcre"}`, "", `"Amg6nZWXKB6YpNgBPv9atcjdm6hnFvs5wMdRgb2e9DmaF5g9muF2"`)
  4701  	if err != nil {
  4702  		t.Error(err)
  4703  	}
  4704  }
  4705  
  4706  func TestUtf(t *testing.T) {
  4707  	bc, err := LoadDummyChain()
  4708  	if err != nil {
  4709  		t.Errorf("failed to create test database: %v", err)
  4710  	}
  4711  	defer bc.Release()
  4712  
  4713  	definition := `
  4714  	function string.tohex(str)
  4715      return (str:gsub('.', function (c)
  4716          return string.format('%02X', string.byte(c))
  4717      end))
  4718  	end
  4719  
  4720  	function query()
  4721  		assert (utf8.char(256) == json.decode('"\\u0100"'), "test1")
  4722  		a = utf8.char(256,128)
  4723  		b = utf8.char(256,10000,45)
  4724  		assert(string.len(a) == 4 and utf8.len(a) == 2, "test2")
  4725  
  4726  		for p,c in utf8.codes(a) do
  4727  			if p == 1 then
  4728  				assert(c == 256, "test11")
  4729  			else
  4730  				assert(c == 128, "test12")
  4731  			end
  4732  		end
  4733  		assert(utf8.offset(b,1)==1, "test3")
  4734  		assert(utf8.offset(b,2)==3, "test4")
  4735  		assert(utf8.offset(b,3)==6, "test5")
  4736  
  4737  		assert(utf8.codepoint(b,1)==256, "test6")
  4738  
  4739  		k1, k2, k3 = utf8.codepoint(b,1,3)
  4740  		assert(k1 == 256 and k2 == 10000 and k3 == nil, "test7" .. k1 .. k2)
  4741  		
  4742  		k1, k2, k3 = utf8.codepoint(b,1,6)
  4743  		assert(k1 == 256 and k2 == 10000 and k3 == 45, "test7" .. k1 .. k2 .. k3)
  4744  	end
  4745  
  4746  	function query2()
  4747  		a = bignum.number(1000000000000)
  4748  		b = bignum.number(0)
  4749  		return (bignum.tobyte(a)):tohex(), (bignum.tobyte(b)):tohex()
  4750  	end
  4751  
  4752  	function query3()
  4753  		a = bignum.number(-1)
  4754  		return (bignum.tobyte(a)):tohex()
  4755  	end
  4756  	abi.register(query, query2, query3)
  4757  	`
  4758  
  4759  	err = bc.ConnectBlock(
  4760  		NewLuaTxAccount("ktlee", 100),
  4761  		NewLuaTxDef("ktlee", "utf", 0, definition),
  4762  	)
  4763  	if err != nil {
  4764  		t.Error(err)
  4765  	}
  4766  
  4767  	err = bc.Query("utf", `{"Name":"query"}`, "", "")
  4768  	if err != nil {
  4769  		t.Error(err)
  4770  	}
  4771  	err = bc.Query("utf", `{"Name":"query2"}`, "", `["E8D4A51000","00"]`)
  4772  	if err != nil {
  4773  		t.Error(err)
  4774  	}
  4775  	err = bc.Query("utf", `{"Name":"query3"}`, "bignum not allowed negative value", "")
  4776  	if err != nil {
  4777  		t.Error(err)
  4778  	}
  4779  }
  4780  
  4781  func TestLuaCryptoVerifyProof(t *testing.T) {
  4782  	bc, err := LoadDummyChain()
  4783  	if err != nil {
  4784  		t.Errorf("failed to create test database: %v", err)
  4785  	}
  4786  	defer bc.Release()
  4787  
  4788  	definition := `
  4789  	function hextobytes(str)
  4790  		return (str:gsub('..', function (cc)
  4791  			return string.char(tonumber(cc, 16))
  4792  		end))
  4793  	end
  4794  
  4795  	function verifyProofRaw(data)
  4796  		local k = "a6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49"
  4797  		local v = "2710"
  4798  		local p0 = "f871a0379a71a6fb36a75e085aff02beec9f5934b9648d24e2901da307492219608b3780a006a684f73e33f5c18739fd1339977f6fe328eb5cbe64239244b0cec88744355180808080a023866491ea0336f72e659c2a7daf61285de093b04fa353c48069a807c2ba845f808080808080808080"
  4799  		local p1 = "e5a03eb5be412f275a18f6e4d622aee4ff40b21467c926224771b782d4c095d1444b83822710"
  4800  		local b = crypto.verifyProof(hextobytes(k), hextobytes(v), crypto.keccak256(hextobytes(p0)), hextobytes(p0), hextobytes(p1))
  4801  		return b
  4802  	end
  4803  
  4804  	function verifyProofHex(data)
  4805  		local k = "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49"
  4806  		local v = "0x2710"
  4807  		local p0 = "0xf871a0379a71a6fb36a75e085aff02beec9f5934b9648d24e2901da307492219608b3780a006a684f73e33f5c18739fd1339977f6fe328eb5cbe64239244b0cec88744355180808080a023866491ea0336f72e659c2a7daf61285de093b04fa353c48069a807c2ba845f808080808080808080"
  4808  		local p1 = "0xe5a03eb5be412f275a18f6e4d622aee4ff40b21467c926224771b782d4c095d1444b83822710"
  4809  		local b = crypto.verifyProof(k, v, crypto.keccak256(p0), p0, p1)
  4810  		return b
  4811  	end
  4812  
  4813  	abi.register(verifyProofRaw, verifyProofHex)`
  4814  
  4815  	err = bc.ConnectBlock(
  4816  		NewLuaTxAccount("ktlee", 100),
  4817  		NewLuaTxDef("ktlee", "eth", 0, definition),
  4818  	)
  4819  	if err != nil {
  4820  		t.Error(err)
  4821  	}
  4822  
  4823  	err = bc.Query("eth", `{"Name":"verifyProofRaw"}`, "", `true`)
  4824  	if err != nil {
  4825  		t.Error(err)
  4826  	}
  4827  
  4828  	err = bc.Query("eth", `{"Name":"verifyProofHex"}`, "", `true`)
  4829  	if err != nil {
  4830  		t.Error(err)
  4831  	}
  4832  }
  4833  
  4834  func TestMultiArray(t *testing.T) {
  4835  	bc, err := LoadDummyChain()
  4836  	if err != nil {
  4837  		t.Errorf("failed to create test database: %v", err)
  4838  	}
  4839  	defer bc.Release()
  4840  
  4841  	definition := `
  4842  	state.var{
  4843  		mcounts = state.map(2),
  4844  		array = state.array(10, 11),
  4845  		tcounts = state.map(3)
  4846  	}
  4847  
  4848  	function inc()
  4849  		a = system.getItem("key1")
  4850  		if (a == nil) then
  4851  			system.setItem("key1", 1)
  4852  			return
  4853  		end
  4854  		system.setItem("key1", a + 1)
  4855  		mcounts[system.getSender()]["key1"] = a + 1
  4856  		array[1][10] = "k"
  4857  		array[10][5] = "l"
  4858  		tcounts[0][0][0] = 2
  4859  	end
  4860  	function query(a)
  4861  		return system.getItem("key1"), mcounts[a]["key1"], tcounts[0][0][0], tcounts[1][2][3], array:length(), array[1]:length()
  4862  	end
  4863  	function del()
  4864  		tcounts[0][0]:delete(0)
  4865  		tcounts[1][2]:delete(3)
  4866  	end
  4867  	function iter(a)
  4868  		local rv = {}
  4869  		for i, x in array:ipairs() do 
  4870  			for j, y in x:ipairs() do 
  4871  				if y ~= nil then
  4872  					rv[i..","..j] =  y
  4873  				end
  4874  			end
  4875  		end
  4876  		return rv
  4877  	end
  4878  
  4879  	function seterror()
  4880  		rv, err = pcall(function () mcounts[1]["k2y1"] = 4 end)
  4881  		assert(rv == false and string.find(err, "string expected, got number"))
  4882  		rv, err = pcall(function () mcounts["middle"] = 4 end)
  4883  		assert(rv == false and string.find(err, "not permitted to set intermediate dimension of map"))
  4884  		rv, err = pcall(function () array[1] = 4 end)
  4885  		assert(rv == false and string.find(err, "not permitted to set intermediate dimension of array"))
  4886  		rv, err = pcall(function () tcounts[0]:delete(0) end)
  4887  		assert(rv == false and string.find(err, "not permitted to set intermediate dimension of map"))
  4888  		rv, err = pcall(function () tcounts[0][1]:delete() end)
  4889  		assert(rv == false and string.find(err, "invalid key type: 'no value', state.map: 'tcounts'"))
  4890  		rv, err = pcall(function () array[0]:append(2) end)
  4891  		assert(rv == false and string.find(err, "the fixed array cannot use 'append' method"))
  4892  		rv, err = pcall(function () state.var {k = state.map(6)} end)
  4893  		assert(rv == false and string.find(err, "dimension over max limit"), err)
  4894  		rv, err = pcall(function () state.var {k = state.array(1,2,3,4,5,6)} end)
  4895  		assert(rv == false and string.find(err, "dimension over max limit"), err)
  4896  	end
  4897  
  4898  	abi.register(inc, query, iter, seterror, del)
  4899  	abi.payable(inc)`
  4900  
  4901  	err = bc.ConnectBlock(
  4902  		NewLuaTxAccount("ktlee", 100),
  4903  		NewLuaTxDef("ktlee", "ma", 0, definition),
  4904  	)
  4905  	if err != nil {
  4906  		t.Error(err)
  4907  	}
  4908  	err = bc.ConnectBlock(
  4909  		NewLuaTxCall("ktlee", "ma", 0, `{"Name": "inc", "Args":[]}`),
  4910  	)
  4911  	if err != nil {
  4912  		t.Error(err)
  4913  	}
  4914  	err = bc.ConnectBlock(
  4915  		NewLuaTxCall("ktlee", "ma", 0, `{"Name": "inc", "Args":[]}`),
  4916  	)
  4917  	if err != nil {
  4918  		t.Error(err)
  4919  	}
  4920  	err = bc.Query("ma", fmt.Sprintf(`{"Name":"query", "Args":["%s"]}`,
  4921  		types.EncodeAddress(strHash("ktlee"))), "", "[2,2,2,{},10,11]")
  4922  	if err != nil {
  4923  		t.Error(err)
  4924  	}
  4925  	err = bc.ConnectBlock(
  4926  		NewLuaTxCall("ktlee", "ma", 0, `{"Name": "del", "Args":[]}`),
  4927  	)
  4928  	if err != nil {
  4929  		t.Error(err)
  4930  	}
  4931  	err = bc.Query("ma", fmt.Sprintf(`{"Name":"query", "Args":["%s"]}`,
  4932  		types.EncodeAddress(strHash("ktlee"))), "", "[2,2,{},{},10,11]")
  4933  	if err != nil {
  4934  		t.Error(err)
  4935  	}
  4936  	err = bc.Query("ma", `{"Name":"iter"}`, "", `{"1,10":"k","10,5":"l"}`)
  4937  	if err != nil {
  4938  		t.Error(err)
  4939  	}
  4940  	err = bc.Query("ma", `{"Name":"seterror"}`, "", ``)
  4941  	if err != nil {
  4942  		t.Error(err)
  4943  	}
  4944  	definition2 := `
  4945  state.var {
  4946    -- global map
  4947    alpha = state.map(2),
  4948    beta = state.map(2),
  4949  }
  4950  
  4951  function constructor()
  4952  
  4953    local d = alpha["dict"]
  4954    d["a"] = "A"
  4955    alpha["dict"]["b"] = "B"
  4956  
  4957    assert(alpha["dict"]["a"]=="A" and alpha["dict"]["b"]=="B")
  4958  
  4959    -- with local variable
  4960    local d2 = beta["dict"]
  4961    d2["a"] = "A"
  4962    d2["value"] = "v0"
  4963    beta["dict"]["b"] = "B"
  4964    beta["dict"]["value"] = "v1"
  4965    assert(beta["dict"]["a"]=="A" and beta["dict"]["b"]=="B" and beta["dict"]["value"]=="v1")
  4966  end
  4967  
  4968  function abc()
  4969    local d = alpha["dict"]
  4970    d["c"] = "C"
  4971    alpha["dict"]["d"] = "D"
  4972  
  4973    local d = beta["dict"]
  4974    d["a"] = "A"
  4975    d["value"] = "v2"
  4976    beta["dict"]["b"] = "B"
  4977    beta["dict"]["value"] = "v3"
  4978    return alpha["dict"]["c"], alpha["dict"]["d"], beta["dict"]["a"], beta["dict"]["b"], beta["dict"]["value"]
  4979  end
  4980  
  4981  function query()
  4982    return alpha["dict"]["a"], alpha["dict"]["b"], alpha["dict"]["c"], alpha["dict"]["d"], 
  4983  beta["dict"]["a"], beta["dict"]["b"], beta["dict"]["value"] 
  4984  end
  4985  
  4986  abi.register(abc, query)
  4987  `
  4988  	err = bc.ConnectBlock(
  4989  		NewLuaTxAccount("ktlee", 100),
  4990  		NewLuaTxDef("ktlee", "ma", 0, definition2),
  4991  	)
  4992  	err = bc.Query("ma", `{"Name":"query", "Args":[]}`,
  4993  		"", `["A","B",{},{},"A","B","v1"]`)
  4994  	if err != nil {
  4995  		t.Error(err)
  4996  	}
  4997  	tx := NewLuaTxCall("ktlee", "ma", 0, `{"Name": "abc", "Args":[]}`)
  4998  	err = bc.ConnectBlock(tx)
  4999  	if err != nil {
  5000  		t.Error(err)
  5001  	}
  5002  	receipt := bc.getReceipt(tx.hash())
  5003  	if receipt.GetRet() != `["C","D","A","B","v3"]` {
  5004  		t.Errorf("contract Call ret error :%s", receipt.GetRet())
  5005  	}
  5006  	err = bc.Query("ma", `{"Name":"query", "Args":[]}`,
  5007  		"", `["A","B","C","D","A","B","v3"]`)
  5008  	if err != nil {
  5009  		t.Error(err)
  5010  	}
  5011  }
  5012  
  5013  func TestNDeploy(t *testing.T) {
  5014  	bc, err := LoadDummyChain()
  5015  	if err != nil {
  5016  		t.Errorf("failed to create test database: %v", err)
  5017  	}
  5018  	defer bc.Release()
  5019  
  5020  	definition := `
  5021  function constructor()
  5022    testall()
  5023  end
  5024  
  5025  function testall()
  5026    deploytest()
  5027    sendtest()
  5028  end
  5029  
  5030  function deploytest()
  5031    src = [[
  5032    function default()
  5033      contract.send(system.getSender(), system.getAmount())
  5034    end
  5035  
  5036    function getargs(...)
  5037      tb = {...}
  5038    end
  5039  
  5040    abi.payable(default)
  5041    abi.register(getargs)
  5042    ]]
  5043  
  5044    addr = contract.deploy(src)
  5045    id = 'deploy_src'; system.setItem(id, addr)
  5046    system.print(id, system.getItem(id))
  5047  
  5048    korean_char_src = [[
  5049    function 함수()
  5050      변수 = 1
  5051      결과 = 변수 + 3
  5052      system.print('결과', 결과)
  5053    end
  5054  
  5055    abi.register(함수)
  5056    ]]
  5057  
  5058    
  5059    korean_char_src222 = [[
  5060      function default()
  5061        contract.send(system.getSender(), system.getAmount())
  5062      end
  5063    
  5064      function getargs(...)
  5065        tb = {...}
  5066      end
  5067    
  5068      function x()
  5069      end
  5070  
  5071      abi.payable(default)
  5072      abi.register(getargs)
  5073    ]]
  5074  
  5075    korean_addr =  contract.deploy(korean_char_src)
  5076    id = 'korean_char_src'; system.setItem(id, korean_addr)
  5077    system.print(id, system.getItem(id))
  5078  end
  5079  
  5080  function sendtest()
  5081    addr = system.getItem("deploy_src")
  5082    system.print('ADDRESS', addr, system.getAmount())
  5083    
  5084    id = 's01'; system.setItem(id,{pcall(function() contract.send(addr, system.getAmount()) end)})
  5085    system.print(id, system.getItem(id))
  5086  end
  5087  
  5088  function default()
  5089    -- do nothing
  5090  end
  5091  
  5092  abi.payable(constructor, default)
  5093  abi.register(testall)
  5094  `
  5095  
  5096  	err = bc.ConnectBlock(
  5097  		NewLuaTxAccount("ktlee", 100),
  5098  		NewLuaTxDef("ktlee", "n-deploy", 0, definition),
  5099  	)
  5100  	if err != nil {
  5101  		t.Error(err)
  5102  	}
  5103  }
  5104  
  5105  func TestJdbcSql(t *testing.T) {
  5106  	bc, err := LoadDummyChain()
  5107  	if err != nil {
  5108  		t.Errorf("failed to create test database: %v", err)
  5109  	}
  5110  	defer bc.Release()
  5111  
  5112  	definition := `
  5113  function init()
  5114      db.exec("create table if not exists total(a int, b int, c text)")
  5115      db.exec("insert into total(a,c) values (1,2)")
  5116      db.exec("insert into total values (2,2,3)")
  5117      db.exec("insert into total values (3,2,3)")
  5118      db.exec("insert into total values (4,2,3)")
  5119      db.exec("insert into total values (5,2,3)")
  5120      db.exec("insert into total values (6,2,3)")
  5121      db.exec("insert into total values (7,2,3)")
  5122  end
  5123  
  5124  function exec(sql, ...)
  5125      local stmt = db.prepare(sql)
  5126      stmt:exec(...)
  5127  end
  5128  
  5129  function query(sql, ...)
  5130      local stmt = db.prepare(sql)
  5131  	local rs = stmt:query(...)
  5132      local r = {}
  5133      local colcnt = rs:colcnt()
  5134  	local colmetas
  5135      while rs:next() do
  5136  		if colmetas == nil then
  5137  			colmetas = stmt:column_info()
  5138  		end
  5139  
  5140  		local k = {rs:get()}
  5141  		for i = 1, colcnt do
  5142  			if k[i] == nil then
  5143  				k[i] = {}
  5144  			end
  5145          end
  5146          table.insert(r, k)
  5147      end
  5148  --  if (#r == 0) then
  5149  --      return {"colcnt":0, "rowcnt":0}
  5150  --  end
  5151  
  5152      return {snap=db.getsnap(), colcnt=colcnt, rowcnt=#r, data=r, colmetas=colmetas}
  5153  end
  5154  
  5155  function queryS(snap, sql, ...)
  5156  	db.open_with_snapshot(snap)
  5157  
  5158      local stmt = db.prepare(sql)
  5159  	local rs = stmt:query(...)
  5160      local r = {}
  5161      local colcnt = rs:colcnt()
  5162  	local colmetas
  5163      while rs:next() do
  5164  		if colmetas == nil then
  5165  			colmetas = stmt:column_info()
  5166  		end
  5167  
  5168  		local k = {rs:get()}
  5169  		for i = 1, colcnt do
  5170  			if k[i] == nil then
  5171  				k[i] = {}
  5172  			end
  5173          end
  5174          table.insert(r, k)
  5175      end
  5176  --  if (#r == 0) then
  5177  --      return {"colcnt":0, "rowcnt":0}
  5178  --  end
  5179  
  5180      return {snap=db.getsnap(), colcnt=colcnt, rowcnt=#r, data=r, colmetas=colmetas}
  5181  end
  5182  function getmeta(sql)
  5183      local stmt = db.prepare(sql)
  5184  
  5185  	return stmt:column_info(), stmt:bind_param_cnt()
  5186  end
  5187  abi.register(init, exec, query, getmeta, queryS)`
  5188  
  5189  	_ = bc.ConnectBlock(
  5190  		NewLuaTxAccount("ktlee", 100000000000000000),
  5191  		NewLuaTxDef("ktlee", "jdbc", 0, definition),
  5192  		NewLuaTxCall("ktlee", "jdbc", 0, `{"Name":"init"}`),
  5193  	)
  5194  
  5195  	err = bc.Query("jdbc", `{"Name":"query", "Args":["select a,b,c from total"]}`, "",
  5196  		`{"colcnt":3,"colmetas":{"colcnt":3,"decltypes":["int","int","text"],"names":["a","b","c"]},"data":[[1,{},"2"],[2,2,"3"],[3,2,"3"],[4,2,"3"],[5,2,"3"],[6,2,"3"],[7,2,"3"]],"rowcnt":7,"snap":"2"}`)
  5197  	if err != nil {
  5198  		t.Error(err)
  5199  	}
  5200  	err = bc.Query("jdbc", `{"Name":"getmeta", "Args":["select a,b,?+1 from total"]}`, "",
  5201  		`[{"colcnt":3,"decltypes":["int","int",""],"names":["a","b","?+1"]},1]`)
  5202  	if err != nil {
  5203  		t.Error(err)
  5204  	}
  5205  	err = bc.ConnectBlock(
  5206  		NewLuaTxCall("ktlee", "jdbc", 0, `{"Name": "exec", "Args":["insert into total values (3,4,5)"]}`),
  5207  	)
  5208  	if err != nil {
  5209  		t.Error(err)
  5210  	}
  5211  	err = bc.Query("jdbc", `{"Name":"query", "Args":["select a,b,c from total"]}`, "",
  5212  		`{"colcnt":3,"colmetas":{"colcnt":3,"decltypes":["int","int","text"],"names":["a","b","c"]},"data":[[1,{},"2"],[2,2,"3"],[3,2,"3"],[4,2,"3"],[5,2,"3"],[6,2,"3"],[7,2,"3"],[3,4,"5"]],"rowcnt":8,"snap":"3"}`)
  5213  	if err != nil {
  5214  		t.Error(err)
  5215  	}
  5216  	err = bc.Query("jdbc", `{"Name":"queryS", "Args":["2", "select a,b,c from total"]}`, "",
  5217  		`{"colcnt":3,"colmetas":{"colcnt":3,"decltypes":["int","int","text"],"names":["a","b","c"]},"data":[[1,{},"2"],[2,2,"3"],[3,2,"3"],[4,2,"3"],[5,2,"3"],[6,2,"3"],[7,2,"3"]],"rowcnt":7,"snap":"3"}`)
  5218  	if err != nil {
  5219  		t.Error(err)
  5220  	}
  5221  }
  5222  
  5223  // end of test-cases