1. 程式人生 > >星雲鏈智能合約開發(四):在星雲鏈上發送交易

星雲鏈智能合約開發(四):在星雲鏈上發送交易

星雲鏈智能合約開發 在星雲鏈上發送交易

準備賬戶

在星雲鏈上,每個地址表示一個唯一的賬戶,一一對應。

在發送交易前,我們需要準備兩個賬戶:一個賬戶用來發送代幣 (稱為"from") 和另一個賬戶來接受代幣 (稱為"to").

發送者賬戶

在這裏,我們將會使用配置文件conf/default/genesis.conf中預分配過代幣的賬戶中選擇一個作為發送者賬戶,我選擇:n1XkoVVjswb5Gek3rRufqjKNpwrDdsnQ7Hq。

接受者賬戶

我們使用如下指令創建一個全新的賬戶來做接受者,請記住輸入的密碼。

$ ./neb account new
Your new account is locked with a passphrase. Please give a passphrase. Do not forget this passphrase.
Passphrase:         #設置密碼
Repeat passphrase:  #確認設置的密碼

執行結果:

Address: n1UCDvzgjk5mPCtFtcpjYQWnnaVx8a8g5rL

n1UCDvzgjk5mPCtFtcpjYQWnnaVx8a8g5rL即為新賬號,新賬戶的keystore文件將會被放置在$GOPATH/src/github.com/nebulasio/go-nebulas/keydir/內。

Keystore 文件是以星雲鏈存儲私鑰的一種文件格式 (JSON)。它使用用戶自定義密碼加密,以起到一定程度上的保護作用,而保護的程度取決於用戶加密該錢包的密碼強度,如果類似於 123456 這樣的密碼,是極為不安全的。 在使用 Keystore 時有兩點需要註意:1. 使用不常用,並且盡可能復雜的密碼加密 Keystore 文件;2. 一定要記住加密 Keystore 的密碼,一旦忘記密碼,那麽你就失去了 Keystore 的使用權

Keystore內容如下:

{
    "address": "n1UCDvzgjk5mPCtFtcpjYQWnnaVx8a8g5rL",
    "crypto": {
        "cipher": "aes-128-ctr",
        "ciphertext": "52a9403411fecf7b98f16b485634450f2087fa99d70ac8bfe883bae8b96e4d7d",
        "cipherparams": {
            "iv": "9ae06485a0c1e3d853e7383c518e0804"
        },
        "kdf": "scrypt",
        "kdfparams": {
            "dklen": 32,
            "n": 4096,
            "p": 1,
            "r": 8,
            "salt": "845fb918f7bf28ac514cd5dd716cef97948ff248a307a24d820607ff4e75f7e1"
        },
        "mac": "8d26f96b9c8c300db97858f306677bed3b33e017425aad4292eb3b02cfc0ab1f",
        "machash": "sha3256"
    },
    "id": "5121caf3-e328-434c-b91f-8b3c2aa1f258",
    "version": 4
}

啟動私有鏈

見《星雲鏈智能合約開發(三):運行星雲鏈》

星雲鏈交互,在鏈上發送交易

星雲鏈提供給開發者HTTP API, RPC API和CLI來和運行中的星雲節點交互,HTTP API(API Module | Admin Module)。星雲鏈的HTTP服務默認端口號為8685。

檢查賬戶狀態

我們可以通過API Module中的/v1/user/accountstate接口來獲取賬戶信息

使用curl工具,命令行輸入:

curl -i -H Accept:application/json -X POST http://localhost:8685/v1/user/accountstate -d ‘{"address":"n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE"}‘

執行結果:

{
    "result": {
        "balance": "5000000000000000000000000",
        "nonce": "0",
        "type": 87
    }
}
  • Type用於標記賬戶類型。88表示該賬戶為智能合約賬戶,部署一個合約之後,就可以得到一個合約賬戶。87表示非合約賬戶,我們通過./neb account new創建的賬戶就是非合約賬戶,用戶存儲鏈上資產。
  • Nonce用於標記賬戶發起的所有交易的順序。同一個賬戶,每發起一個新的交易,Nonce就加一,初始為0,第一個交易的Nonce為1。
  • balance為賬戶余額,5000000000000000000000000(5 * 10^24)表示5NAS

發送交易

Nebulas提供了三種方式去發送我們的交易:

  • 簽名 & 發送
  • 密碼 & 發送
  • 解鎖 & 發送

    簽名 & 發送

    使用這種方式,我們可以在離線環境下先使用私鑰簽名好交易,然後把簽好名的交易在聯網的機器上發出。這是最安全的發送交易的方式,私鑰可以完全離線保存,不觸網。Web-Wallet正是基於Neb.js采用這種方法發送的交易。

首先,我們使用Admin Module中的v1/admin/sign接口給準備發的交易簽名,得到交易的二進制數據。

curl -i -H ‘Content-Type: application/json‘ -X POST http://localhost:8685/v1/admin/sign -d ‘{"transaction":{"from":"n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE","to":"n1QZMXSZtW7BUerroSms4axNfyBGyFGkrh5", "value":"1000000000000000000","nonce":1,"gasPrice":"1000000","gasLimit":"2000000"}, "passphrase":"passphrase"}‘

執行結果:

{
    "result": {
        "data": "CiAbjMP5dyVsTWILfXL1MbwZ8Q6xOgX/JKinks1dpToSdxIaGVcH+WT/SVMkY18ix7SG4F1+Z8evXJoA35caGhlXbip8PupTNxwV4SRM87r798jXWADXpWngIhAAAAAAAAAAAA3gtrOnZAAAKAEwuKuC1wU6CAoGYmluYXJ5QGRKEAAAAAAAAAAAAAAAAAAPQkBSEAAAAAAAAAAAAAAAAAAehIBYAWJBVVuRHWSNY1e3bigbVKd9i6ci4f1LruDC7AUtXDLirHlsmTDZXqjSMGLio1ziTmxYJiLj+Jht5RoZxFKqFncOIQA="
    }
}

在發送交易時,對於同一個賬戶,只有當他Nonce為N的交易上鏈後,Nonce為N+1的交易才能上鏈,有嚴格的順序,Nonce必須嚴格加1。可以通過GetAccountState接口查看最新的Nonce。

然後,我們將簽好名的交易原始數據提交到本地私有鏈裏的星雲節點,下面的data字段的內容就是上面產生的。

curl -i -H ‘Content-Type: application/json‘ -X POST http://localhost:8685/v1/user/rawtransaction -d ‘{"data":"CiAbjMP5dyVsTWILfXL1MbwZ8Q6xOgX/JKinks1dpToSdxIaGVcH+WT/SVMkY18ix7SG4F1+Z8evXJoA35caGhlXbip8PupTNxwV4SRM87r798jXWADXpWngIhAAAAAAAAAAAA3gtrOnZAAAKAEwuKuC1wU6CAoGYmluYXJ5QGRKEAAAAAAAAAAAAAAAAAAPQkBSEAAAAAAAAAAAAAAAAAAehIBYAWJBVVuRHWSNY1e3bigbVKd9i6ci4f1LruDC7AUtXDLirHlsmTDZXqjSMGLio1ziTmxYJiLj+Jht5RoZxFKqFncOIQA="}‘

執行結果:

{
    "result": {
        "txhash": "1b8cc3f977256c4d620b7d72f531bc19f10eb13a05ff24a8a792cd5da53a1277",
        "contract_address": ""
    }
}

密碼 & 發送

如果你信任一個星雲節點幫你保存keystore文件,你可以使用第二種方法發送交易。

首先,上傳你的keystore文件到你信任的星雲節點的keydir文件夾下,我們前面在本地創建的賬號的keystore自動存儲在keydir下。

然後,我們發送交易的同時,帶上我們keystore的密碼,在被信任的節點使用SendTransactionWithPassphrase接口上一次性完成簽名和發送過程。

curl -i -H ‘Content-Type: application/json‘ -X POST http://localhost:8685/v1/admin/transactionWithPassphrase -d ‘{"transaction":{"from":"n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE","to":"n1QZMXSZtW7BUerroSms4axNfyBGyFGkrh5", "value":"1000000000000000000","nonce":2,"gasPrice":"1000000","gasLimit":"2000000"},"passphrase":"passphrase"}‘

執行結果:

{
    "result": {
        "txhash": "3cdd38a66c8f399e2f28134e0eb556b292e19d48439f6afde384ca9b60c27010",
        "contract_address": ""
    }
}

解鎖 & 發送

這是最危險的發送交易的方法。除非你完全信任一個星雲節點,否則不要使用這種方法來發送交易。

首先,上傳你的keystore文件到你信任的星雲節點的keydir文件夾下。

然後,使用你的keystore文件的密碼,在指定的時間範圍來在被信任的節點上使用Unlock接口解鎖賬戶。時間單位為納秒,300000000000為300s,表示300s也就是5分鐘內賬戶都處於解鎖狀態,直接進行操作不再需要驗證。

curl -i -H ‘Content-Type: application/json‘ -X POST http://localhost:8685/v1/admin/account/unlock -d ‘{"address":"n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE","passphrase":"passphrase","duration":"300000000000"}‘

執行成功後的結果:

{"result":{"result":true}}

然後,發送交易

curl -i -H ‘Content-Type: application/json‘ -X POST http://localhost:8685/v1/admin/transaction -d ‘{"from":"n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE","to":"n1QZMXSZtW7BUerroSms4axNfyBGyFGkrh5", "value":"1000000000000000000","nonce":3,"gasPrice":"1000000","gasLimit":"2000000"}‘

執行結果:

{
    "result": {
        "txhash": "8d69dea784f0edfb2ee678c464d99e155bca04b3d7e6cdba6c5c189f731110cf",
        "contract_address": ""
    }
}

交易收據

不論使用的哪一種方法發送交易,我們都會得到兩個返回值,txhash和contract_address。其中txhash為交易hash,是一個交易的唯一標識。如果當前交易是一個部署合約的交易,contract_address將會是合約地址,調用合約時都會使用這個地址,是合約的唯一標識。

使用txhash我們可以查看交易收據,知道當前交易的狀態。

curl -i -H Accept:application/json -X POST http://localhost:8685/v1/user/getTransactionReceipt -d ‘{"hash":"8d69dea784f0edfb2ee678c464d99e155bca04b3d7e6cdba6c5c189f731110cf"}‘

執行結果:

{
    "result": {
        "hash": "8d69dea784f0edfb2ee678c464d99e155bca04b3d7e6cdba6c5c189f731110cf",
        "chainId": 100,
        "from": "n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE",
        "to": "n1QZMXSZtW7BUerroSms4axNfyBGyFGkrh5",
        "value": "1000000000000000000",
        "nonce": "3",
        "timestamp": "1524667888",
        "type": "binary",
        "data": null,
        "gas_price": "1000000",
        "gas_limit": "2000000",
        "contract_address": "",
        "status": 1,
        "gas_used": "20000"
    }
}

這裏的status可能有三種狀態值,0,1和2。

  • 0: 交易失敗. 表示當前交易已經上鏈,但是執行失敗了。可能是因為部署合約或者調用合約參數錯誤。
  • 1: 交易成功. 表示當前交易已經上鏈,而且執行成功了。
  • 2: 交易待定. 表示當前交易還沒有上鏈。可能是因為當前交易還沒有被打包;如果長時間處於當前狀態,可能是因為當前交易的發送者賬戶的余額不夠支付上鏈手續費。

星雲鏈智能合約開發(四):在星雲鏈上發送交易