Bytom DAPP Development Notes (2): development process

Time:2020-8-16

brief introduction

The content of this chapter analyzes in detail the whole development process of DAPP involving smart contract. Note that only contract is involved. If you only need some basic BTM functions, it is not of great significance. This content will supplement the official provided Compared with the original chain DAPP development process, the detailed practice of some holes, and some real specific skills and experience, I think it is very useful, at least let developers operate more quickly.

According to the data, the deposit dividend contract is too complicated. Simply talk about the logic. The bank sends a share asset, locks it with the contract, and the user triggers the contract. After paying money for the corresponding share of the stock asset, when it reaches a certain height, it can be converted back to the principal and dividend (money + interest) by using the share asset. It contains two contracts~~

Overall process

The development process is divided into: 1) write smart contract; 2) issue contract transaction; 3) test unlock contract method; 4) develop DAPP front-end based on plug-in wallet; 5) develop back-end;

The process seems very simple. I wasted a lot of time in steps 1, 2 and 3. Some of the pits have been stepped on. Let’s introduce them next;

1)Write smart contractCompared with the original DAPP development process, the above description is very clear. The use of equity is very simple. You can download the latest version of DAPP directly and get a series of compiled contract program code with the command [. / equity tradeoffer — instance], which is referred to as the smart contract program.

E:\GoWorks\src\github.com\equity\equity>equity.exe jiedai_6.txt --instance ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 260374 260474 260574 260674 260774 260874 260874 00141ccef16d2ac1ab22baa8acfa1633fdc32df
d55aa b1f38553d95177c53755996baf523da006da977008f069792bb6a2c3b6a253fb

======= PartLoanCollateral =======
Instantiated program:

20b1f38553d95177c53755996baf523da006da977008f069792bb6a2c3b6a253fb1600141ccef16d2ac1ab22baa8acfa1633fdc32dfd55aa030afb03030afb0303a6fa030342fa0303def903037af9030316f90320ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffff4d2b015b7a76529c641d010000640c0100005c7900a0695c790500f2052a01947600a0695379cd9f5579cda09a916164380000005a95639a00000054798ccd9f5679cda09a916164500000005895639a00000055798ccd9f5779cda09a916164680000005695639a00000056798ccd
9f5879cda09a916164800000005495639a00000057798ccd9f5979cda09a916164980000005295639a0000005195c3787ca169c3787c9f916164f5000000005e795479515e79c1695178c2516079c16952c3527994c251006079895f79895e79895d79895c79895b79895a79895979895879
895779895679890274787e008901c07ec1696307010000005e795479515e79c16951c3c2516079c169632b010000587acd9f6900c3c2515c7ac1632b010000755b7aaa5b7a8800c3c2515d7ac1747800c0

2)Contract tradingLet’s first explain the logic of the contract. The savings dividend contract is too complicated, so we use theCurrency transactionTake the contract as an example,

contract TradeOffer(assetRequested: Asset,

                    amountRequested: Amount,

                    seller: Program,

                    cancelKey: PublicKey) locks valueAmount of valueAsset {

  clause trade() {

    lock amountRequested of assetRequested with seller

    unlock valueAmount of valueAsset

  }

  clause cancel(sellerSig: Signature) {

    verify checkTxSig(cancelKey, sellerSig)

    unlock valueAmount of valueAsset

  }

}

Take a look at the transaction chart of the smart contract to make it easier for Xiaobai to understand:

Bytom DAPP Development Notes (2): development process

Therefore, the deposit dividend contract must lock in some assets at the beginning, so contract transaction must be deployed. So how to trigger it?

I deploy the contract through the interface of PC wallet. Many specific examples can be seen in the smart contract learning document.

In PC wallet mode, all transactions must have three interfaces: build transaction, sign transaction and submit transaction.

A hole that has been trodden

  1. The debugging of smart contract is very slow. We can know whether it is successful until the transaction is confirmed. Moreover, the error is not obvious, and we don’t know where the problem is;

    Solution:

Debug the local PC wallet in solonet mode, change the source code, and quickly output diffculty/ difficulty.go

func CheckProofOfWork(hash, seed *bc.Hash, bits uint64) bool { 
    compareHash := tensority.AIHash.Hash(hash, seed)   
    return HashToBig(compareHash).Cmp(CompactToBig(bits)) <= 0
}         

Add “true” to the sentence below

return HashToBig(compareHash).Cmp(CompactToBig(bits)) <= 0 || true

At first, I didn’t expect to do this. I thought that the debugging would be finished soon. I did it for three days at 10:00 p.m.

2Support for divisionIt’s very unfriendly. Try not to use division. At the beginning, I wrote a very complicated contract. I didn’t know the error. I changed the code step by step and quickly debugged to locate the location. Finally, I found that a / B was OK. If a = B, it would report an error directly. If I asked the official, I didn’t get an appropriate answer. I tried to solve this problem. It’s very pitiful.

3. The program must calculate the input and output of the corresponding utxo flow action; as follows

{

 "base_transaction": null,
 "actions": [
   {
     "output_id": "13fbd1e5df196a1488e85e3b5983e51444c49ef3695df789c9473abb636e0f5c",
     "arguments": [
       {
         "type": "integer",
         "raw_data": {
           "value": 5500000000
         }
       },   {
               "type": "data",
               "raw_data": {
                   "value": "00141ccef16d2ac1ab22baa8acfa1633fdc32dfd55aa"
               }
           },
           {
             "type": "integer",
             "raw_data": {
               "value": 0
             }
           }
         ],
         "type": "spend_account_unspent_output"
       },
       {
         "amount": 5500000000,
         "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
         "control_program": "0014d470cdd1970b58b32c52ecc9e71d795b02c79a65",
         "type": "control_program"
       },
       {
         "amount": 5000000000,
         "asset_id": "80013f81a66cb99977879e31639bb4fe4b12b4c7050fe518585d3f7f159d26a9",
         "control_program": "00141ccef16d2ac1ab22baa8acfa1633fdc32dfd55aa",
         "type": "control_program"
       },
       {
         "amount": 9999995000000000,
         "asset_id": "80013f81a66cb99977879e31639bb4fe4b12b4c7050fe518585d3f7f159d26a9",
         "control_program": "20b1f38553d95177c53755996baf523da006da977008f069792bb6a2c3b6a253fb160014d470cdd1970b58b32c52ecc9e71d795b02c79a6503e1830403e1830403e256040322350403a21e0403e20e040307fb0320ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d2b015b7a76529c641d010000640c0100005c7900a0695c790500f2052a01947600a0695379cd9f5579cda09a916164380000005a95639a00000054798ccd9f5679cda09a916164500000005895639a00000055798ccd9f5779cda09a916164680000005695639a00000056798ccd9f5879cda09a916164800000005495639a00000057798ccd9f5979cda09a916164980000005295639a0000005195c3787ca169c3787c9f916164f5000000005e795479515e79c1695178c2516079c16952c3527994c251006079895f79895e79895d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696307010000005e795479515e79c16951c3c2516079c169632b010000587acd9f6900c3c2515c7ac1632b010000755b7aaa5b7a8800c3c2515d7ac1747800c0",
         "type": "control_program"
       },
       {
         "account_id": "0U374V0300A02",
         "amount": 5500000000,
         "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
         "type": "spend_account"
       },
       {
         "account_id": "0U374V0300A02",
         "amount": 20000000,
         "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
         "type": "spend_account"
       }
     ],
     "ttl": 10000
   }

An unlock contract transaction should contain action types such as,

spend_account_unspent_output(parameters of the contract),

spend_account(asset description entered),

control_ Program or control_ address(receiver asset description),

It can be understood asmass conservation

Like the example above

spend_ account_ unspent_ There is an output in the action of output_ Id = 13fbd1e5df196a1488e85e3b5983e51444c49ef3695df789c9473abb636e0f5c, the decimal place of this asset is 8 (not reflected here), which means that I want to unlock the utxo. Its value is 1000000000.00000000, which is 100 million.

Split into two actions, one is 50.00000000, and the other is 9999950.00000000

Only BTM = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff.

summary: then the program is equivalent to integrating the logic in the contract to calculate the real input and output ~ ~ I understand that when the transaction is confirmed, the program that unlocks the contract verifies whether the current input and output are the same as the contract.

3) Test unlock contract method(2) this problem has been explained clearly in the mining pit. It is better not to write too complicated contract at once, but to develop and debug from a simple point of view. We must pay attention to the law of conservation of mass, as long as we understand this principle, it is actually very simple.

4) Development of DAPP front end based on plug-in WalletThis can be seen in the plug-in wallet API and the front-end source code of savings and bonus contract. The interface involved is very clear. For the time being, their API documents have not been sorted out, which comes from the interface of blockcenter mentioned in the previous chapter

URL address: testnet: ‘ http://app.bycoin.io :3020/’, mainnet: ‘ https://api.bycoin.im :8000/’

The interfaces used in the core include:

Query utxo interface according to contract and asset ID

/api/v1/btm/q/list-utxos

Parameters:
{    
    "filter": {                    "script":"20b1f38553d95177c53755996baf523da006da977008f069792bb6a2c3b6a253fb160014d470cdd1970b58b32c52ecc9e71d795b02c79a6503e1830403e1830403e256040322350403a21e0403e20e040307fb0320ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d2b015b7a76529c641d010000640c0100005c7900a0695c790500f2052a01947600a0695379cd9f5579cda09a916164380000005a95639a00000054798ccd9f5679cda09a916164500000005895639a0000798ccd9f5779cda09a916164680000005695639a00000056798ccd9f5879cda09a916164800000005495639a00000057798ccd9f5979cda09a916164980000005295639a0000005195c3787ca169c3787c9f916164f5000000005e795479515e79c1695178c2516079c16952c3527994c251006079895f79895e79895d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696307010000005e795479515e79c16951c3c2516079c169632b010000587acd9f6900c3c2515c7ac1632b010000755b7aaa5b7a8800c3c2515d7ac1747800c0", 
        "asset":"80013f81a66cb99977879e31639bb4fe4b12b4c7058585d3f7f159d26a9" ,
        "unconfirmed":false
    },    
    "sort":  {
        "by":"amount", 
        "order":"desc" 
        }
}

Unconfirmed stands for confirmation. This is very useful for concurrency problems in later stages. I will explain it in detail in Chapter 3.

result
{
    "code": 200,
    "msg": "",
    "result": {
        "_links": {},
        "data": [
            {
                "hash": "16749b694a9f1bc6a7759cf66baefed4c864b65985e7488e8721184ecc4d6965",
                "asset": "80013f81a66cb99977879e31639bb4fe4b12b4c7058585d3f7f159d26a9",
                "amount": 3000000000
            },
            {
                "hash": "e5f75036b6f662ff705378b55dd29dc1a43acb23d701dd44a068cdab2c43ad0c",
                "asset": "80013f81a66cb99977879e31639bb4fe4b12b4c7058585d3f7f159d26a9",
                "amount": 15000000000
            }
        ],
        "limit": 10,
        "start": 0
    }
}

(prepare the parameter call by yourself. The above is just an example.)

Query user address information and balance interface

/api/v1/btm/account/list-addresses

parameter

{"guid":"b414005b-b501-4a0e-8b0f-e1cd762272f4"}

result

{

    "code": 200,

    "msg": "",

    "result": {

        "_links": {},

        "data": [{

            "guid": "b414005b-b501-4a0e-8b0f-e1cd762272f4",

            "address": "bm1qp4t6thlyktt6sh02scs8dqcpnk3ufk9e9pmq9s",

            "label": "",

            "balances": [{

                "asset": "80013f81a66cb99977879e31639bb4fe4b12b4c7050fe518585d3f7f159d26a9",

                "balance": "68900000000",

                "total_received": "69000000000",

                "total_sent": "100000000",

                "decimals": 8,

                "alias": "",

                "in_usd": "0.00",

                "in_cny": "0.00",

                "in_btc": "0.000000"

            }, {

                "asset": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",

                "balance": "1329551000",

                "total_received": "53790000000",

                "total_sent": "52460449000",

                "decimals": 8,

                "alias": "btm",

                "in_usd": "1.45",

                "in_cny": "10.10",

                "in_btc": "0.000142"

            }]

        }],

        "limit": 10,

        "start": 0

    }

}

ps:

GUI is the only one provided by the plug-in wallet. This is very useful. I will talk about it in detail in Chapter 3.

Query transaction information

/api/v1/btm/account/list-transactions

parameter

{"address":"bm1qp4t6thlyktt6sh02scs8dqcpnk3ufk9e9pmq9s","start":0,"limit":100}

result

{
    "code": 200,
    "msg": "",
    "result": {
        "data": [{
            "ID": 111,
            "Hash": "471e5b267f646546be33505773186ee9d8dde2180a515df67a90d1a5f9d17bd2",
            "AssetID": "80013f81a66cb99977879e31639bb4fe4b12b4c7050fe518585d3f7f159d26a9",
            "Amount": 7000000000,
            "Address": "bm1qp4t6thlyktt6sh02scs8dqcpnk3ufk9e9pmq9s",
            "BaseID": 5,
            "Timestamp": "2019-07-08T09:23:12+08:00",
            "Height": 263728,
            "TransactionID": "471e5b267f646546be33505773186ee9d8dde2180a515df67a90d1a5f9d17bd2",
            "InputAmount": 5700000000
        }, {
            "ID": 64,
            "Hash": "e69631a8d6321d738793646399ffe022ac177a5732f562970e706ee76d49de82",
            "AssetID": "80013f81a66cb99977879e31639bb4fe4b12b4c7050fe518585d3f7f159d26a9",
            "Amount": 5000000000,
            "Address": "bm1qp4t6thlyktt6sh02scs8dqcpnk3ufk9e9pmq9s",
            "BaseID": 5,
            "Timestamp": "2019-07-05T16:37:07+08:00",
            "Height": 262170,
            "TransactionID": "e69631a8d6321d738793646399ffe022ac177a5732f562970e706ee76d49de82",
            "InputAmount": 5500000000
        }, {
            "ID": 56,
            "Hash": "cf74906808a1a6bc6a056c148510d542a10d2cbc350a4d830c670aa5ba973873",
            "AssetID": "80013f81a66cb99977879e31639bb4fe4b12b4c7050fe518585d3f7f159d26a9",
            "Amount": 39000000000,
            "Address": "bm1qp4t6thlyktt6sh02scs8dqcpnk3ufk9e9pmq9s",
            "BaseID": 5,
            "Timestamp": "2019-07-03T14:59:22+08:00",
            "Height": 261006,
            "TransactionID": "cf74906808a1a6bc6a056c148510d542a10d2cbc350a4d830c670aa5ba973873",
            "InputAmount": 8900000000
        }, {
            "ID": 54,
            "Hash": "6aedf609d47b3c06de2ce7dc9f2c99895124c80074573cd29407ac3b34ef8d40",
            "AssetID": "80013f81a66cb99977879e31639bb4fe4b12b4c7050fe518585d3f7f159d26a9",
            "Amount": 2000000000,
            "Address": "bm1qp4t6thlyktt6sh02scs8dqcpnk3ufk9e9pmq9s",
            "BaseID": 5,
            "Timestamp": "2019-07-03T12:11:12+08:00",
            "Height": 260936,
            "TransactionID": "6aedf609d47b3c06de2ce7dc9f2c99895124c80074573cd29407ac3b34ef8d40",
            "InputAmount": 5200000000
        }]
    }
}

5) The development of the back-end is equivalent to a buffer server. In Chapter 3, I will explain in detail the source code content of the buffer server and the holes it has stepped on.

Summary:

The content of this chapter is mainly cumbersome. It emphasizes the debugging contract, which is the core problem. A problem is raised here, that is, the utxo problem. The debugging process is very complicated. Originally, the blockchain does not do high concurrency, but there are also concurrency problems. How should we solve them? Some friends who have used the PC wallet must know that the utxo in the PC wallet is locked in the transaction process, so it is impossible to operate the next one. Some utxo are OK. If there is only one, it is very troublesome to debug and use it ~ ~ ~ Chapter 3 we are based on the originalbufferserverOn the basis of the official scheme, we will change it to a certain extent to solve the concurrency problem. We are looking forward to it.

reference material:

DAPP development process of the original chain

Visit address of demo

Source code of buffer server at the back end of savings dividend contract

Savings dividend contract front-end source code

Details of savings dividend contract

equity

Smart contract learning document

Plug in wallet API

Author: the bucket of genius