Hello World

Smart Contracts Quick Start Guide

WaykiChain DAPP Foundation

A blockchain can be abstracted into a state machine that is synchronized across the network. A smart contract is code that executes on a blockchain system and changes the state in the state machine through transactions. Due to the characteristics of the blockchain, the call of the smart contract can be guaranteed to be serial and globally consistent.

WaykiChain smart contract currently supports Lua language development, and does not support multi-contract calls. [Learning Lua Language] (https://www.runoob.com/lua/lua-basic-syntax.html)

Key words

Keywords Description
contract The default global variable name inside the smart contract, used to get external call parameters inside the smart contract, type is table
mylib Smart Contract Internal API Interface
[Common Methods] (./common_func.md) Common Methods for Smart Contract Development, Based on Lua Language
[mylib use case] (./api_debug.md) Common use cases based on mylib package
WaykiMix Smart Contract Development Online IDE
WaykiBridge DAPP Wallet Interface Unification Tool
BaaS WaykiChain Blockchain Public API

Debug environment configuration

WaykiChain smart contract development and deployment environment support [WaykiMix] (../DeveloperHelper/waykimix.md) online deployment and call, build [local test network node] (../NodeDeployment/testnet.md) can be more convenient debug.

Smart contract basic structure

demo.lua

Mylib = require "mylib"

Main = function()

End

Main()

Helloworld Smart Contract Source

The entry to the smart contract is the Main function, and the Main function contains two different functional methods.

SayHelloToLog() is used to output Hello World! in the log.

SaveHelloToChain() is used to write Hello-World to LevelDB in the blockchain as key-value, which can be found in BaaS Query the corresponding value.

Mylib = require "mylib"
-- The script must start with `mylib = require "mylib"`. Be sure to put it in the first line. If the first line is left blank, an exception will be reported.

--Define contract call events
METHOD = {
    SAYHELLOTOLOG = 0x17,
    SAVEHELLOTOCHAIN ​​= 0x18
}

LOG_TYPE =
{
    ENUM_STRING = 0,
    ENUM_NUMBER = 1
}

-- used to output log information to a file
LogMsg = function(LogType, Value)
    Local LogTable = {
        Key = 0, --log type: string or number
        Length = 0, the total length of the --value data stream
        Value = nil -- string or number stream
    }
    --Save data stream
    LogTable.key = LogType
    LogTable.length = #Value
    LogTable.value = Value
    mylib.LogPrint(LogTable)
End

-- Write key-value key-value pairs to the blockchain
WriteStrkeyValueToDb = function (Strkey, ValueTbl)
    Local t = type(ValueTbl)
    Assert(t == "table","the type of Value isn't table.")

    Local writeTbl = {
        Key = Strkey,
        Length = #ValueTbl,
        Value = {}
    }
    writeTbl.value = ValueTbl

    If not mylib.WriteData(writeTbl) then error("WriteData error") end
End

-- Get information about the calling contract
-- The parameter startIndex is the starting index, the length is the length of the obtained field, and the contract is a global variable.
-- return contract with startIndex as the starting index, length for the length of the contract part of the field
GetContractTxParam = function (startIndex, length)
    Assert(startIndex > 0, "GetContractTxParam start error(<=0).")
    Assert(length > 0, "GetContractTxParam length error(<=0).")
    Assert(startIndex+length-1 <= #contract, "GetContractTxParam length ".. length .." exceeds limit: " .. #contract)

    Local newTbl = {}
    Local i = 1
    For i = 1, length do
        newTbl[i] = contract[startIndex+i-1]
    End
    Return newTbl
End

-------------------------------------------------- -

SayHelloToLog = function()
    LogMsg(LOG_TYPE.ENUM_STRING,"Hello World!")
End

SaveHelloToChain = function(contextTbl)
    WriteStrkeyValueToDb("Hello", contextTbl)
    LogMsg(LOG_TYPE.ENUM_STRING,"Save Hello To Chain Successfully!")
End

--Smart contract entry
Main = function()
  Assert(#contract >=4, "Param length error (<4): " ..#contract )
  Assert(contract[1] == 0xf0, "Param MagicNo error (~=0xf0): " .. contract[1])

  If contract[2] == METHOD.SAYHELLOTOLOG then
    SayHelloToLog()
  Elseif contract[2] == METHOD.SAVEHELLOTOCHAIN ​​then
    Local contextTbl = GetContractTxParam(5,5)--Get the information of the calling contract == "World"
    SaveHelloToChain(contextTbl)
  Else
    Error('method# '..string.format("%02x", contract[2])..' not found')
  End
End

Main()


Deploying smart contracts

Deploy to test network via WaykiMix

Deploy to the test network via the local node RPC submitcontractdeploytx

// Request
Curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"submitcontractdeploytx","params":["wLWxCRWDTb3fUTa6ztoTTCzFwDqzbckSJ7","/tmp/lua/helloworld .lua",110000000]}' -H 'content-type:application/json;' http://127.0.0.1:6967

// Response
{
    "result":
    {
        "hash":"dfdb78278c486016a8588c6ac525eced4348725f5a85af51c898fed320e72e23"
    },
    "error": null,
    "id": "curltext"
}

Query smart contract regid

Query smart contract regid by WaykiMix

Query smart contract regid via local node RPC getcontractregid

// Request
Curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"getcontractregid","params":["dfdb78278c486016a8588c6ac525eced4348725f5a85af51c898fed320e72e23"]}' -H 'content- Type:application/json;' http://127.0.0.1:6967

// Response
{
    "result":
    {
        "regid:":"320561-1",
        "regid_hex" : "31e404000100"
    },
    "error": null,
    "id": "curltext"
}

Calling Smart Contract 1

Here the contract is passed in the parameter f0170000. According to the contract source, the SayHelloToLog() method is called, ie `Hello World!" is printed in the log.

[Parameter Description for Smart Contract Call] (./develop_guide.md/)

Parameter parsing of the calling contract

               +--------+--------------+-------+
               Magic number + specified contract method | Reserved bits |
"f0170000" = +--------+--------------+-------+
               | 0xf0 | 0x17 | 0000 |
               +--------+--------------+-------+

Calling Smart Contracts via WaykiMix

Calling a smart contract via the local node RPC submitcontractcalltx

// Request
Curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"submitcontractcalltx","params":["wLWxCRWDTb3fUTa6ztoTTCzFwDqzbckSJ7","320561-1",0 ,"f0170000",1000000]}' -H 'content-type:application/json;' http://127.0.0.1:6967

// Response
{
    "result":
    {
       "hash":"f867200b3d91fd2cbf8b0d8b8840e64bf620f08923acc3126fb960dd04b3064f"
    },
    "error": null,
    "id": "curltext"
}

View log

The premise is to add debug=vm to the local node WaykiChain.conf to view the vm.log information in the corresponding directory. The screenshot shows that the log information is the running content of the Check method in the contract, that is, output Hello World! information to the vm.log file.

Calling Smart Contract 2

Here the contract is passed in the parameter f0180000576f726c64, and the SAVEHELLOTOCHAIN() method is called according to the contract source. The 5 bytes of the parameters of the calling contract are taken as the value value, and "Hello" is written as the key value in the LevelDB of the blockchain.

[Parameter Description for Smart Contract Call] (./develop_guide.md/)

Parameter parsing of the calling contract

                         +--------+--------------+-------+------------+
                         Magic * The specified contract method | Reserved bits | "World" |
"f0180000576f726c64" = +--------+--------------+-------+------------+
                         0xf0 | 0x18 | 0000 | 576f726c64 |
                         +--------+--------------+-------+------------+

Calling Smart Contracts via WaykiMix

Calling a smart contract via the local node RPC submitcontractcalltx

// Request
Curl -u Waykichain:admin -d '{"jsonrpc":"2.0","id":"curltext","method":"callcontracttx","params":["wLWxCRWDTb3fUTa6ztoTTCzFwDqzbckSJ7","320561-1",0 ,"f0180000576f726c64",1000000]}' -H 'content-type:application/json;' http://127.0.0.1:6967

// Response
{
    "result":
    {
       "hash":"f65fc179dd9056b06a4a843ee696afa115678bdad523440ae6facd98e7d61a9d"
    },
    "error": null,
    "id": "curltext"
}

Query key-value values ​​with WaykiMix