diff --git a/account/wallet_test.go b/account/wallet_test.go
index 4eb40a8..9d7ec27 100644
--- a/account/wallet_test.go
+++ b/account/wallet_test.go
@@ -18,15 +18,16 @@ package account
import (
"fmt"
+ "os"
+ "runtime"
+ "strconv"
+ "testing"
+
"github.com/Zilliqa/gozilliqa-sdk/core"
provider2 "github.com/Zilliqa/gozilliqa-sdk/provider"
"github.com/Zilliqa/gozilliqa-sdk/transaction"
"github.com/Zilliqa/gozilliqa-sdk/util"
"github.com/stretchr/testify/assert"
- "os"
- "runtime"
- "strconv"
- "testing"
)
func TestPayload(t *testing.T) {
@@ -172,7 +173,7 @@ func TestSendTransactionInsufficientAmount(t *testing.T) {
Version: strconv.FormatInt(int64(util.Pack(333, 1)), 10),
SenderPubKey: "0246E7178DC8253201101E18FD6F6EB9972451D121FC57AA2A06DD5C111E58DC6A",
ToAddr: "4BAF5faDA8e5Db92C3d3242618c5B47133AE003C",
- Amount: "10000000000000000",
+ Amount: "2000000000000000000",
GasPrice: gasPrice,
GasLimit: "1",
Code: "",
diff --git a/contract/contract.go b/contract/contract.go
index 1b330fb..999c722 100644
--- a/contract/contract.go
+++ b/contract/contract.go
@@ -22,11 +22,20 @@ import (
"github.com/Zilliqa/gozilliqa-sdk/core"
"github.com/Zilliqa/gozilliqa-sdk/provider"
"github.com/Zilliqa/gozilliqa-sdk/transaction"
+ "github.com/Zilliqa/gozilliqa-sdk/util"
+ "strconv"
"strings"
)
type ContractStatus int
+const MainNet = "mainnet"
+const TestNet = "testnet"
+const Isolated = "isolated"
+const TestNetHost = "https://dev-api.zilliqa.com/"
+const MainNetHost = "https://api.zilliqa.com/"
+const IsolatedHost = "https://zilliqa-isolated-server.zilliqa.com/"
+
const (
Deployed ContractStatus = iota
Rejected
@@ -49,6 +58,58 @@ type State struct {
core.ContractValue
}
+// This a shortcut function to deploy smart contract, all following parameters would remain default:
+// network id, message version nonce, gasfee, gaslimit
+// take a note that for gas limit, 40k is safe and recommend setting number
+// value of network can be testnet, mainnet or isolated
+func (c *Contract) DeployTo(network string) (*transaction.Transaction, error) {
+ if network == TestNet {
+ c.Provider = provider.NewProvider(TestNetHost)
+ gasPrice, err := c.Provider.GetMinimumGasPrice()
+ if err != nil {
+ return nil, err
+ }
+ parameter := DeployParams{
+ Version: strconv.FormatInt(int64(util.Pack(333, 1)), 10),
+ Nonce: "",
+ GasPrice: gasPrice,
+ GasLimit: "40000",
+ SenderPubKey: "",
+ }
+ return c.Deploy(parameter)
+ } else if network == MainNet {
+ c.Provider = provider.NewProvider(MainNetHost)
+ gasPrice, err := c.Provider.GetMinimumGasPrice()
+ if err != nil {
+ return nil, err
+ }
+ parameter := DeployParams{
+ Version: strconv.FormatInt(int64(util.Pack(1, 1)), 10),
+ Nonce: "",
+ GasPrice: gasPrice,
+ GasLimit: "40000",
+ SenderPubKey: "",
+ }
+ return c.Deploy(parameter)
+ } else if network == Isolated {
+ c.Provider = provider.NewProvider(IsolatedHost)
+ gasPrice, err := c.Provider.GetMinimumGasPrice()
+ if err != nil {
+ return nil, err
+ }
+ parameter := DeployParams{
+ Version: strconv.FormatInt(int64(util.Pack(1, 1)), 10),
+ Nonce: "",
+ GasPrice: gasPrice,
+ GasLimit: "40000",
+ SenderPubKey: "",
+ }
+ return c.Deploy(parameter)
+ } else {
+ return nil, errors.New("unsupported network, please use testnet, mainnet or isolated")
+ }
+}
+
func (c *Contract) Deploy(params DeployParams) (*transaction.Transaction, error) {
if c.Code == "" || c.Init == nil || len(c.Init) == 0 {
return nil, errors.New("Cannot deploy without code or initialisation parameters.")
@@ -133,6 +194,58 @@ func (c *Contract) Sign(transition string, args []core.ContractValue, params Cal
return nil, tx
}
+func (c *Contract) CallFor(transition string, args []core.ContractValue, priority bool, amount string, network string) (*transaction.Transaction, error) {
+ if network == TestNet {
+ c.Provider = provider.NewProvider(TestNetHost)
+ gasPrice, err := c.Provider.GetMinimumGasPrice()
+ if err != nil {
+ return nil, err
+ }
+ params := CallParams{
+ Version: strconv.FormatInt(int64(util.Pack(333, 1)), 10),
+ Nonce: "",
+ GasPrice: gasPrice,
+ GasLimit: "40000",
+ Amount: amount,
+ SenderPubKey: "",
+ }
+ return c.Call(transition, args, params, priority)
+ } else if network == MainNet {
+ c.Provider = provider.NewProvider(MainNetHost)
+ gasPrice, err := c.Provider.GetMinimumGasPrice()
+ if err != nil {
+ return nil, err
+ }
+ params := CallParams{
+ Version: strconv.FormatInt(int64(util.Pack(1, 1)), 10),
+ Nonce: "",
+ GasPrice: gasPrice,
+ GasLimit: "40000",
+ Amount: amount,
+ SenderPubKey: "",
+ }
+ return c.Call(transition, args, params, priority)
+ } else if network == Isolated {
+ c.Provider = provider.NewProvider(IsolatedHost)
+ gasPrice, err := c.Provider.GetMinimumGasPrice()
+ if err != nil {
+ return nil, err
+ }
+ params := CallParams{
+ Version: strconv.FormatInt(int64(util.Pack(1, 1)), 10),
+ Nonce: "",
+ GasPrice: gasPrice,
+ GasLimit: "40000",
+ Amount: amount,
+ SenderPubKey: "",
+ }
+ return c.Call(transition, args, params, priority)
+ } else {
+ return nil, errors.New("unsupported network, please use testnet, mainnet or isolated")
+ }
+
+}
+
func (c *Contract) Call(transition string, args []core.ContractValue, params CallParams, priority bool) (*transaction.Transaction, error) {
if c.Address == "" {
_ = errors.New("Contract has not been deployed!")
diff --git a/contract/contract_test.go b/contract/contract_test.go
index 40f83c4..d349015 100644
--- a/contract/contract_test.go
+++ b/contract/contract_test.go
@@ -17,6 +17,7 @@
package contract
import (
+ "fmt"
"github.com/Zilliqa/gozilliqa-sdk/core"
"github.com/stretchr/testify/assert"
"io/ioutil"
@@ -30,6 +31,63 @@ import (
"github.com/Zilliqa/gozilliqa-sdk/util"
)
+func TestContract_DeployTo(t *testing.T) {
+ if os.Getenv("CI") != "" {
+ t.Skip("Skipping testing in CI environment")
+ }
+
+ privateKey := "e19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930"
+ wallet := account.NewWallet()
+ wallet.AddByPrivateKey(privateKey)
+
+ publickKey := keytools.GetPublicKeyFromPrivateKey(util.DecodeHex(privateKey), true)
+ address := keytools.GetAddressFromPublic(publickKey)
+ code, _ := ioutil.ReadFile("./fungible.scilla")
+ init := []core.ContractValue{
+ {
+ "_scilla_version",
+ "Uint32",
+ "0",
+ },
+ {
+ "owner",
+ "ByStr20",
+ "0x" + address,
+ },
+ {
+ "total_tokens",
+ "Uint128",
+ "1000000000",
+ },
+ {
+ "decimals",
+ "Uint32",
+ "0",
+ },
+ {
+ "name",
+ "String",
+ "BobCoin",
+ },
+ {
+ "symbol",
+ "String",
+ "BOB",
+ },
+ }
+
+ contract := Contract{
+ Code: string(code),
+ Init: init,
+ Signer: wallet,
+ }
+
+ tx, err := contract.DeployTo(TestNet)
+ assert.Nil(t, err, err)
+ tx.Confirm(tx.ID, 1000, 10, contract.Provider)
+ assert.True(t, tx.Status == core.Confirmed)
+}
+
func TestContract_Deploy(t *testing.T) {
if os.Getenv("CI") != "" {
t.Skip("Skipping testing in CI environment")
@@ -105,6 +163,43 @@ func TestContract_Deploy(t *testing.T) {
assert.True(t, tx.Status == core.Confirmed)
}
+func TestContract_CallFor(t *testing.T) {
+ if os.Getenv("CI") != "" {
+ t.Skip("Skipping testing in CI environment")
+ }
+
+ privateKey := "e19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930"
+ wallet := account.NewWallet()
+ wallet.AddByPrivateKey(privateKey)
+ publickKey := keytools.GetPublicKeyFromPrivateKey(util.DecodeHex(privateKey), true)
+ address := keytools.GetAddressFromPublic(publickKey)
+ fmt.Println(address)
+
+ contract := Contract{
+ Address: "bd7198209529dC42320db4bC8508880BcD22a9f2",
+ Signer: wallet,
+ }
+
+ args := []core.ContractValue{
+ {
+ "to",
+ "ByStr20",
+ "0x" + address,
+ },
+ {
+ "tokens",
+ "Uint128",
+ "10",
+ },
+ }
+
+ tx, err2 := contract.CallFor("Transfer", args, true, "0", TestNet)
+ assert.Nil(t, err2, err2)
+ tx.Confirm(tx.ID, 1000, 3, contract.Provider)
+ assert.True(t, tx.Status == core.Confirmed)
+
+}
+
func TestContract_Call(t *testing.T) {
if os.Getenv("CI") != "" {
t.Skip("Skipping testing in CI environment")
diff --git a/core/types.go b/core/types.go
index d46692e..9cc9e85 100644
--- a/core/types.go
+++ b/core/types.go
@@ -156,6 +156,12 @@ type ContractValue struct {
Value interface{} `json:"value"`
}
+type ParamConstructor struct {
+ Constructor string `json:"constructor"`
+ ArgTypes []interface{} `json:"argtypes"`
+ Arguments []string `json:"arguments"`
+}
+
type BalanceAndNonce struct {
Balance string `json:"balance"`
Nonce int64 `json:"nonce"`
diff --git a/schnorr/schnorr_signer_wrapper.go b/schnorr/schnorr_signer_wrapper.go
new file mode 100644
index 0000000..b2e7b03
--- /dev/null
+++ b/schnorr/schnorr_signer_wrapper.go
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Zilliqa
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/*
+ * This module is a mini wrapper around the main schnorr module used for
+ * zilliqa rosetta project. It includes the generation of the random bytes
+ * to make the signing process more convenient.
+ */
+package go_schnorr
+
+import (
+ "encoding/hex"
+ "fmt"
+
+ "github.com/Zilliqa/gozilliqa-sdk/keytools"
+ "github.com/Zilliqa/gozilliqa-sdk/util"
+)
+
+func SignMessage(privateKey []byte, publicKey []byte, message []byte) ([]byte, error) {
+ // generate a random byte k
+ rb, err := keytools.GenerateRandomBytes(keytools.Secp256k1.N.BitLen() / 8)
+
+ if err != nil {
+ return nil, err
+ }
+
+ r, s, err2 := TrySign(privateKey, publicKey, message, rb)
+
+ if err2 != nil {
+ return nil, err2
+ }
+
+ sig := fmt.Sprintf("%064s%064s", util.EncodeHex(r), util.EncodeHex(s))
+ sigBytes, err := hex.DecodeString(sig)
+
+ if err != nil {
+ panic("cannot convert hex string to byte array")
+ }
+
+ return sigBytes, nil
+}
+
+func VerifySignature(publicKey []byte, message []byte, signature []byte) bool {
+ sig := util.EncodeHex(signature)
+
+ if len(sig) != 128 {
+ fmt.Printf("invalid signature length: %v\n", len(sig))
+ return false
+ }
+
+ r := util.DecodeHex(sig[0:64])
+ s := util.DecodeHex(sig[64:128])
+
+ return Verify(publicKey, message, r, s)
+}
diff --git a/schnorr/schnorr_signer_wrapper_test.go b/schnorr/schnorr_signer_wrapper_test.go
new file mode 100644
index 0000000..d5ef01c
--- /dev/null
+++ b/schnorr/schnorr_signer_wrapper_test.go
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 Zilliqa
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package go_schnorr
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "testing"
+
+ golangAssert "github.com/stretchr/testify/assert"
+)
+
+func TestSignVerify(t *testing.T) {
+ run_sign_verify_test(t)
+}
+
+func run_sign_verify_test(t *testing.T) {
+ b, err := ioutil.ReadFile("data")
+ if err != nil {
+ panic("read file failed")
+ }
+
+ var data []map[string]string
+ err2 := json.Unmarshal(b, &data)
+
+ if err2 != nil {
+ panic("unmarshal failed")
+ }
+
+ for _, v := range data {
+ msg := hex_bytes(v["msg"])
+ pub := hex_bytes(v["pub"])
+ priv := hex_bytes(v["priv"])
+
+ sig, err := SignMessage(priv, pub, msg)
+
+ if err != nil {
+ fmt.Printf("err = %s\n", err.Error())
+ } else {
+ verify := VerifySignature(pub, msg, sig)
+
+ fmt.Printf("signature = %v\n", sig)
+ fmt.Printf("expected verify = %v\n", true)
+ fmt.Printf("actually verify = %v\n", verify)
+ golangAssert.True(t, verify, "verify should be true")
+ }
+ }
+}