Skip to content

Commit

Permalink
KLC-119 Sign Message (#6)
Browse files Browse the repository at this point in the history
* Add signableMessage helper

* Load json

* move proto to folder

* include tests

* makefile tests

* validate address len

* refact: create func to create packInfo

Co-authored-by: hyperyuri <yuri.snp@hotmail.com>
  • Loading branch information
fbsobreira and 2yuri authored Oct 25, 2022
1 parent 01c5691 commit e55e103
Show file tree
Hide file tree
Showing 30 changed files with 731 additions and 136 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
bin/
vendor
.idea

.vscode
.vscode
*.out
out.svg
35 changes: 34 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,47 @@ endif
ldflags := -X 'main.appVersion=${VERSION}'

GOCMD=go
GOIMPORT=goimports
GOINSTALL=$(GOCMD) install
GOTEST=$(GOCMD) test
GORUN=$(GOCMD) run -ldflags="$(ldflags)"
GOBUILD=$(GOCMD) build -ldflags="$(ldflags)"


############################
### DEMO APP ###
############################
.PHONY: demo-getAccount demo-transfer demo-createAsset
demo.%: DEMO=$*
demo.%:
$(GORUN) ./cmd/demo/$(DEMO)

############################
### TESTS/COVERAGE ###
############################
.PHONY: dependencies vet test test_coverage

dependencies:
$(GOINSTALL) github.com/nikolaydubina/go-cover-treemap@latest
$(GOINSTALL) golang.org/x/tools/cmd/goimports@latest

vet:
$(GOCMD) vet ./...

imports:
$(eval CHECKFILES = $(shell find . -type f -name '*.go' -not -name '*.pb.go' -not -name '*_setter.go' -not -path './vendor/*'))
$(GOCMD) mod tidy
$(GOIMPORT) -d -w $(CHECKFILES)

test:
$(GOCMD) clean -testcache
$(GOTEST) ./...

test_coverage:
$(eval PACKAGES = $(shell go list ./... | grep -v '/proto/'))
$(GOTEST) -coverprofile cover.out $(PACKAGES)
go-cover-treemap -coverprofile cover.out > out.svg

test_coveragehtml:
$(eval PACKAGES = $(shell go list ./... | grep -v '/proto/'))
$(GOTEST) -coverprofile cover.out $(PACKAGES)
$(GOCMD) tool cover -html=cover.out
3 changes: 2 additions & 1 deletion cmd/demo/createAsset/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/klever-io/klever-go-sdk/cmd/demo"
"github.com/klever-io/klever-go-sdk/models"
"github.com/klever-io/klever-go-sdk/models/proto"
)

func main() {
Expand All @@ -17,7 +18,7 @@ func main() {
base := accounts[0].NewBaseTX()
tx, err := kc.CreateKDA(
base,
models.KDAData_Fungible,
proto.KDAData_Fungible,
&models.KDAOptions{
Name: "KleverTest",
Ticker: "TST",
Expand Down
24 changes: 24 additions & 0 deletions core/address/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ import (
func TestAddress_ZeroAddress(t *testing.T) {
addr := address.ZeroAddress()
assert.Equal(t, addr.Bech32(), "klv1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpgm89z")
assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(addr.Bytes()))
}

func TestAddress_InvalidSize(t *testing.T) {
_, err := address.NewAddressFromBytes([]byte("000"))
assert.Contains(t, err.Error(), "decoding address, expected length 32")

_, err = address.NewAddressFromHex("000")
assert.Contains(t, err.Error(), "encoding/hex: odd length hex string")

_, err = address.NewAddressFromHex("0000")
assert.Contains(t, err.Error(), "decoding address, expected length")
}

func TestAddress_Address_ShouldFail(t *testing.T) {
Expand All @@ -29,6 +41,18 @@ func TestAddress_Address_ShouldFail(t *testing.T) {
// invalid bech32 prefix
_, err = address.NewAddress("kfi1qy352eufzqg3yyc5z5v3wxqeyqsjygeyy5nzw2pfxqcnyve5x5mq7ze5xk")
assert.NotNil(t, err)

// invalid decoded len
_, err = address.NewAddress("klv1d05ju9jaj6u99zph0ant9jjv3jkq")
assert.Contains(t, err.Error(), "invalid incomplete group")

_, err = address.NewAddress("klv1xqcrqt6vdma")
assert.Contains(t, err.Error(), "decoding address, expected length 32")

// invalid checksum
_, err = address.NewAddress("klv1d05ju9jaj6u99zph0ant9jh7gksg")
assert.Contains(t, err.Error(), "invalid checksum")

}

func TestAddress_Address_ShouldWork(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions core/wallet/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ type Wallet interface {
PublicKey() []byte
GetAccount() (account.Account, error)
Sign(msg []byte) ([]byte, error)
SignHex(msg string) ([]byte, error)
}
2 changes: 1 addition & 1 deletion core/wallet/pem.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func LoadKey(pemFile string, skIndex int, pwd string) ([]byte, string, error) {

encodedSk, pkString, err := LoadSkPkFromPemFile(pemFile, skIndex, pwd)
if err != nil {
return nil, "", nil
return nil, "", err
}

skBytes, err := hex.DecodeString(string(encodedSk))
Expand Down
159 changes: 159 additions & 0 deletions core/wallet/pem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package wallet_test

import (
"encoding/hex"
"io/ioutil"
"log"
"testing"

"github.com/klever-io/klever-go-sdk/core/wallet"
"github.com/stretchr/testify/assert"
)

func tempPemFile() string {
file, err := ioutil.TempFile("", "wallet*.pem")
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString(
`-----BEGIN PRIVATE KEY for klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy-----
ODczNDA2MmMxMTU4ZjI2YTNjYThhNGEwZGE4N2I1MjdhN2MxNjg2NTNmN2Y0Yzc3
MDQ1ZTVjZjU3MTQ5N2Q5ZA==
-----END PRIVATE KEY for klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy-----`)

return file.Name()
}

func tempPemFileEncrypted() string {
file, err := ioutil.TempFile("", "wallet*.pem")
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString(
`-----BEGIN PRIVATE KEY for klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-GCM,453eb5c4c21225936c8c27b2
RT61xMISJZNsjCeyEiLgO/Nftp5Nk/l1OsGg7jlbnk/YDQ6675Nq82qg3U/IIC6b
Y3osGzZtxlO0KWQ9MOeZ1aRkIDl3Mys15RmXEqBBF+Ukqmcm1K2+oupmSgw=
-----END PRIVATE KEY for klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy-----`)

return file.Name()
}

func tempPemFileEncryptedWrong() string {
file, err := ioutil.TempFile("", "wallet*.pem")
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString(
`-----BEGIN PRIVATE KEY for klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256,453eb5c4c21225936c8c27b2
RT61xMISJZNsjCeyEiLgO/Nftp5Nk/l1OsGg7jlbnk/YDQ6675Nq82qg3U/IIC6b
Y3osGzZtxlO0KWQ9MOeZ1aRkIDl3Mys15RmXEqBBF+Ukqmcm1K2+oupmSgw=
-----END PRIVATE KEY for klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy-----`)

return file.Name()
}

func tempEmptyPemFile() string {
file, err := ioutil.TempFile("", "wallet*.pem")
if err != nil {
log.Fatal(err)
}
defer file.Close()

return file.Name()
}

func tempInvalidPemFile() string {
file, err := ioutil.TempFile("", "wallet*.pem")
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString(`-----BEGIN PRIVATE KEY for klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy-----`)

return file.Name()
}

func TestLoadKey_PemFileNotFound(t *testing.T) {

_, _, err := wallet.LoadKey("wallet.pem", 0, "")
assert.Contains(t, err.Error(), "no such file or directory")
}

func TestLoadKey_InvalidPemFile(t *testing.T) {
fileName := tempInvalidPemFile()

_, _, err := wallet.LoadKey(fileName, 0, "")
assert.Contains(t, err.Error(), "invalid pem file while reading")
}

func TestLoadKey_EmptyPemFile(t *testing.T) {
fileName := tempEmptyPemFile()

_, _, err := wallet.LoadKey(fileName, 0, "")
assert.Contains(t, err.Error(), "empty file provided while")
}

func TestLoadKey_InvalidSKIndex(t *testing.T) {
fileName := tempPemFile()

_, _, err := wallet.LoadKey(fileName, -1, "")
assert.Equal(t, "invalid index", err.Error())
}

func TestLoadKey_ShouldWork(t *testing.T) {
fileName := tempPemFile()

pk, pub, err := wallet.LoadKey(fileName, 0, "")
assert.Nil(t, err)
assert.Equal(t, "klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy", pub)
assert.Equal(t, "8734062c1158f26a3ca8a4a0da87b527a7c168653f7f4c77045e5cf571497d9d", hex.EncodeToString(pk))
}

func TestLoadKey_EncryptedShouldWork(t *testing.T) {
fileName := tempPemFileEncrypted()

pk, pub, err := wallet.LoadKey(fileName, 0, "123")
assert.Nil(t, err)
assert.Equal(t, "klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy", pub)
assert.Equal(t, "8734062c1158f26a3ca8a4a0da87b527a7c168653f7f4c77045e5cf571497d9d", hex.EncodeToString(pk))
}

func TestLoadKey_EncryptedWrongPassword(t *testing.T) {
fileName := tempPemFileEncrypted()

_, _, err := wallet.LoadKey(fileName, 0, "")
assert.Contains(t, err.Error(), "encrypted key, must provide password")

_, _, err = wallet.LoadKey(fileName, 0, "1")
assert.Contains(t, err.Error(), "failed PEM decryption")
}

func TestLoadKey_EncryptedWrong(t *testing.T) {
fileName := tempPemFileEncryptedWrong()

_, _, err := wallet.LoadKey(fileName, 0, "22")
assert.Contains(t, err.Error(), "invalid encryption mode")
}

func TestLoadKey_InvalidSKIndexNotFound(t *testing.T) {
fileName := tempPemFile()

_, _, err := wallet.LoadKey(fileName, 1, "")
assert.Contains(t, err.Error(), "invalid index while reading")
}

func TestEncryptPEMBlock_ShouldWork(t *testing.T) {

pem, err := wallet.EncryptPEMBlock("AES-GCM", []byte("8734062c1158f26a3ca8a4a0da87b527a7c168653f7f4c77045e5cf571497d9d"), "123")
assert.Nil(t, err)
assert.Len(t, pem.Bytes, 92)
}
2 changes: 1 addition & 1 deletion core/wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func NewWalletFroHex(privateHex string) (Wallet, error) {
}

func (w *wallet) PrivateKey() []byte {
return append([]byte{}, w.privateKey...)
return w.privateKey[:32]
}

func (w *wallet) PublicKey() []byte {
Expand Down
23 changes: 23 additions & 0 deletions core/wallet/wallet_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
package wallet_test

import (
"encoding/hex"
"testing"

"github.com/klever-io/klever-go-sdk/core/wallet"
"github.com/stretchr/testify/assert"
)

func TestWallet_WalletFromPem(t *testing.T) {
fileName := tempPemFile()
wallet, err := wallet.NewWalletFromPEM(fileName)
assert.Nil(t, err)

assert.Equal(t, "8734062c1158f26a3ca8a4a0da87b527a7c168653f7f4c77045e5cf571497d9d", hex.EncodeToString(wallet.PrivateKey()))
assert.Equal(t, "e41b323a571fd955e09cd41660ff4465c3f44693c87f2faea4a0fc408727c8ea", hex.EncodeToString(wallet.PublicKey()))
}

func TestWallet_Mnemonic(t *testing.T) {
wallet, err := wallet.NewWalletFromMnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about")
assert.Nil(t, err)
Expand All @@ -24,3 +34,16 @@ func TestWallet_PrivateKey(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, acc.Address().Bech32(), "klv1usdnywjhrlv4tcyu6stxpl6yvhplg35nepljlt4y5r7yppe8er4qujlazy")
}

func TestWallet_Sign(t *testing.T) {
wallet, err := wallet.NewWalletFroHex("8734062c1158f26a3ca8a4a0da87b527a7c168653f7f4c77045e5cf571497d9d")
assert.Nil(t, err)

signature, err := wallet.Sign(make([]byte, 32))
assert.Nil(t, err)
assert.Equal(t, "e0cb52c1b61916594daefe04aed24620058204a77e95bbbe5bb4ab165a76eda7d0f316d14d10ef184738f149bb5c0bc96ff4a194c25342dc1f6735a35bda0708", hex.EncodeToString(signature))

hexSign, err := wallet.SignHex("0000000000000000000000000000000000000000000000000000000000000000")
assert.Nil(t, err)
assert.Equal(t, signature, hexSign)
}
31 changes: 31 additions & 0 deletions models/account_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package models_test

import (
"testing"

"github.com/klever-io/klever-go-sdk/models"
"github.com/stretchr/testify/assert"
)

func TestAccount_ToString(t *testing.T) {
acc := &models.Account{
AccountInfo: &models.AccountInfo{
Address: "1234",
},
}
assert.Equal(t,
"{\n\t\"address\": \"1234\",\n\t\"nonce\": 0,\n\t\"balance\": 0,\n\t\"frozenBalance\": 0,\n\t\"allowance\": 0,\n\t\"permissions\": null,\n\t\"timestamp\": 0,\n\t\"assets\": null\n}",
acc.String(),
)
}

func TestAccountAlloance_ToString(t *testing.T) {
acc := &models.AccountAllowance{
Allowance: 123,
StakingRewards: 456,
}
assert.Equal(t,
"{\n\t\"allowance\": 123,\n\t\"stakingRewards\": 456\n}",
acc.String(),
)
}
Loading

0 comments on commit e55e103

Please sign in to comment.