こんにちは、Gincoの永田(@nagatkaz116)です。

皆さんはZilliqaという暗号通貨をご存知でしょうか? シャーディングという手法を用いることで高いトランザクションスループットを実現し、なおかつスマートコントラクトのプラットフォームも提供するZilliqaは、今非常に期待されている暗号通貨の一つです。

弊社ではZilliqaチームのグラントプログラムの一環でZilleanというGolang SDKを開発・管理しています。 今回はZilleanの紹介をさせて頂きます。

Zilleanの機能一覧

Zilleanは大きく分けて2つの機能から成り立ちます。 1つ目がWallet APIであり、鍵生成や署名などの基本的なウォレット機能を提供します。 2つ目がJSON-RPC APIであり、こちらはZilliqaが提供するJSON-RPC APIをGolangで実装したものになります。 以下がそれぞれの機能一覧になります。

  • Wallet API
    • GeneratePrivateKey
    • VerifyPrivateKey
    • GetPublicKeyFromPrivateKey
    • IsPublicKey
    • GetAddressFromPrivateKey
    • GetAddressFromPublicKey
    • IsAddress
    • SignTransaction
    • VerifySignature
  • JSON-RPC API
    • GetBalance
    • GetDsBlock
    • GetTxBlock
    • GetLatestDsBlock
    • GetLatestTxBlock
    • GetTransaction
    • CreateTransaction
    • GetSmartContracts
    • GetSmartContractState
    • GetSmartContractCode
    • GetSmartContractInit
    • GetBlockchainInfo
    • GetNetworkId
    • GetRecentTransactions
    • GetDSBlockListing
    • GetTxBlockListing

Zilleanの使用例1(鍵生成やトランザクション生成)

ここでは秘密鍵の生成からトランザクション生成までを一連の流れの中で解説させて頂きます。

まずはコードをご覧ください。

package main

import (
    "fmt"
    "math/big"

    "github.com/GincoInc/zillean"
)

func main() {
    // initialize the Zillean
    zil := zillean.NewZillean("https://api.zilliqa.com")

    // generate a private key
    privKey := zil.GeneratePrivateKey()
    fmt.Printf("private key: %s\n", privKey) // private key: 3719619964cd1eff62c43f28e9364d43c89de862c1433dbc951ed48524465b27

    // get a public key
    pubKey, _ := zil.GetPublicKeyFromPrivateKey(privKey)
    fmt.Printf("public key: %s\n", pubKey) // public key: 03bc07d6591438da2c221d56704c10bd4606403f053d6219f21bb70a78d611861b

    // get an address
    address, _ := zil.GetAddressFromPrivateKey(privKey)
    fmt.Printf("address: %s\n", address) // address: 35fa7d340a34cc31a72b609702d74fca2cf9dabd

    // sign the transaction
    rawTx := zillean.RawTransaction{
        Version:  0,
        Nonce:    2,
        To:       "to address",
        Amount:   "1000000000000",
        PubKey:   pubKey,
        GasPrice: big.NewInt(1000000000),
        GasLimit: 1,
    }
    
    signature, _ := zil.SignTransaction(rawTx, privKey)
    fmt.Printf("signature: %s\n", signature) // signature: 0c59611561f91108ea547cd56bbe49c321e0b6856238f0f9c5c05535ec9cf9107bbcef6fb2391432224afbf0658c8a000a35f72bb21fd512cf12fd5f6c4f3c4d
    txID, _ := zil.RPC.CreateTransaction(rawTx, signature)
    fmt.Printf("txID: %s\n", txID)
}

順番に説明します。

まず、zilleanオブジェクトを生成しています。 この時の引数にはZilliqaのJSON-RPCエンドポイントを指定してください。 例のままで大丈夫です。

次に鍵を生成しています。 Zilliqaではマルチシグネチャー署名に適したEC-Schnorrと呼ばれる署名アルゴリズムを採用しており、楕円曲線にはsecp256k1を用いています。 この記事ではアルゴリズムの詳細については触れませんが、興味のある方はこちらを参照ください。 ZilleanではEC-Schnorrから実装しています。 今回の例では秘密鍵を新規に生成していますが、GetPublicKeyFromPrivateKey関数やGetAddressFromPrivateKey関数を用いることで、公式のZilliqaウォレットで作成したアカウントを復元することも可能です。

次に署名を行なっています。 この際に、kというランダムな値をGenerateDRN関数を用いて生成する必要があります。 この擬似乱数の存在によって、同じ秘密鍵を用いて同じメッセージに署名を行っても毎回異なる署名が生成されることになります。 ちなみに、GenerateDRN関数はnonceという引数をとりますが、ここではメッセージをnonceに入れています。

最後にトランザクションを生成しています。 前のステップで生成した署名を生トランザクションと共にCreateTransaction関数に渡しています。 ここで、JSON-RPCを用いています。 今回の例では、残高が空のアドレスを用いたり、送信先アドレスに不正なアドレスを入れたりしていて、トランザクション生成に失敗するはずですので、適宜適切なアドレスに置き換えてください。

Zilleanの使用例2(残高確認など)

次にJSON-RPCの使用例として残高取得、トランザクション取得、スマートコントラクト取得を紹介します。 公式ドキュメントも合わせてご覧ください。

以下、コードをご覧ください。

package main

import (
    "fmt"

    "github.com/GincoInc/zillean"
)

func main() {
    // initialize the Zillean
    zil := zillean.NewZillean("https://api.zilliqa.com")

    // get balance
    balance, _ := zil.RPC.GetBalance("546c73019def014ff2e363c4bc97de9ef90354fa")
    fmt.Printf("balance: %s\n", balance.Balance) // balance: 1000000000000
    fmt.Printf("nonce: %d\n", balance.Nonce) // nonce: 0

    // get transaction
    transaction, _ := zil.RPC.GetTransaction("B25E05C30C53B2E2BEEB67B5AAD483069C18D1901B544FD63301DEC6516873DE")
    fmt.Printf("ID: %s\n", transaction.ID) // ID: b25e05c30c53b2e2beeb67b5aad483069c18d1901b544fd63301dec6516873de
    fmt.Printf("amount: %s\n", transaction.Amount) // amount: 1000000000000
    fmt.Printf("gas limit: %s\n", transaction.GasLimit) // gas limit: 1
    fmt.Printf("gas price: %s\n", transaction.GasPrice) // gas price: 1000000000
    fmt.Printf("nonce: %s\n", transaction.Nonce) // nonce: 1
    fmt.Printf("cumulative gas: %s\n", transaction.Receipt.CumulativeGas) // cumulative gas: 1
    fmt.Printf("epoch num: %s\n", transaction.Receipt.EpochNum) // epoch num: 5128
    fmt.Printf("success: %t\n", transaction.Receipt.Success) // success: true
    fmt.Printf("sender pubkey: %s\n", transaction.SenderPubKey) // sender pubkey: 0x02892A6380826988CC46F317310D09F3BAB838B9D8C2407775F20F6AB8BD2A9FFF
    fmt.Printf("signature: %s\n", transaction.Signature) // signature: 0x44509B5C1408B48268062580E74372106983B75C0E8E070086030E0F2D12D32DE94FC644D76F46D3BD4DA5F55FAF04397879CE32FF40A81B3B1FA43EC25B5C04
    fmt.Printf("to address: %s\n", transaction.ToAddr) // to address: 546c73019def014ff2e363c4bc97de9ef90354fa
    fmt.Printf("version: %s\n", transaction.Version) // version: 0

    // get smart contracts
    contracts, _ := zil.RPC.GetSmartContracts("f49f1306bc8fb0cd8167a58a3550c1443072e96b")
    fmt.Printf("address: %s\n", contracts[0].Address) // address: 2112d6eda5d539826e2a2f175d96a181791a34ab
    fmt.Printf("type: %s\n", contracts[0].State[0].Type) // type: Uint128
    fmt.Printf("value: %s\n", contracts[0].State[0].Value) // value: 0
    fmt.Printf("vname: %s\n", contracts[0].State[0].Vname) // vname: _balance
}

まとめ

今回は弊社が開発・管理しているZilliqaのGolang SDKであるZilleanを紹介させて頂きました。 今年の1月にメインネットローンチが予定されており、最近何かと話題になることも多い暗号通貨ですので、これを機に興味を持って頂ければ幸いです。 また、ZilleanはOSSですので、興味を持たれた方は是非開発にもご参加ください。

付録

Zilliqaの公式チームから許可を頂きホワイトペーパーの翻訳をしております。日本語版ホワイトペーパー・PDF版をご覧いただき、ぜひ参考にして頂ければと思います。

また、Web記事版として、こちらからもご覧いただけます。 Zilliqaテクニカルホワイトペーパー翻訳・Web版

Tip us!

エンジニアチームのブログを書くモチベーションが上がります 💪

address

0xd6d478dCe4585a394834690158cf83581223C08f