abi: attempting to unmarshall an empty string while arguments are expected - ethereum

I have a simple solidity code
pragma solidity >0.4.24;
contract Store {
event ItemSet(bytes32 key, bytes32 value);
string public version;
mapping (bytes32 => bytes32) public items;
constructor(string memory _version) public {
version = _version;
}
function setItem(bytes32 key, bytes32 value) external {
items[key] = value;
emit ItemSet(key, value);
}
}
This is the Golang code to call the contract method
auth := bind.NewKeyedTransactor(privateKey)
auth.Nonce = big.NewInt(int64(nonce))
auth.Value = big.NewInt(0) // in wei
auth.GasLimit = uint64(300000) // in units
auth.GasPrice = big.NewInt(0)
address := common.HexToAddress("0xe17a5308f99584834823d2b27B328cb6abaabF11")
instance, err := store.NewStore(address, client)
if err != nil {
log.Fatal(err)
}
key := [32]byte{}
value := [32]byte{}
copy(key[:], []byte("foo"))
copy(value[:], []byte("bar"))
tx, err := instance.SetItem(auth, key, value)
if err != nil {
log.Fatal(err)
}
fmt.Printf("tx sent: %s", tx.Hash().Hex())
result, err := instance.Items(nil, key)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(result[:]))
instance.SetItem(auth, key, value) Calling the SetItem method is successful but when I try to get the Items
tx sent: 0xb8578fb80f7f49d833e05413c957fbd353babe1a993ed96c26b890a1f9cf60fd <-- This hash is for the SetItem
I am getting this error
2019/11/20 23:14:13 abi: attempting to unmarshall an empty string while arguments are expected
Please help on this if anyone has any solution please help me with this error .

You don't have Items function in your contract.

Related

How to marshal an ECC public or private key

Hello i'am trying to unmarshal object that contain ECC public key
but i go umarshaling error saying that can't unmarshal object properly.
i'am tring to do the followeing :
var privateKey *ecdsa.PrivateKey
var publicKey ecdsa.PublicKey
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatalf("Failed to generate ECDSA key: %s\n", err)
}
publicKey = privateKey.PublicKey
marshalledKey, err := json.Marshal(publicKey)
if err != nil {
panic(err)
}
var unmarshalledKey ecdsa.PublicKey
err2 := json.Unmarshal(marshalledKey, &unmarshalledKey)
if err2 != nil {
panic(err2)
}
and tthe error returned from (err2) is :
panic: json: cannot unmarshal object into Go struct field PublicKey.Curve of type elliptic.Curve
and there is no way in either eliptoc or 509x function to umarshal and the curve value is alwayes null
i found the answer finally and i will post it in case somone need it.
all we need is just to creat another struct, lets name it "retrieve" and declare the value it wil read from the unmarshal.
now the ECC public key contain 3 values "curve" and will append it as json:"Curve", "Y" ans will append it as json:"Y" and we will do the same for "X"
and it will work like this :
type retrieve struct {
CurveParams *elliptic.CurveParams `json:"Curve"`
MyX *big.Int `json:"X"`
MyY *big.Int `json:"Y"`
}
//UnmarshalECCPublicKey extract ECC public key from marshaled objects
func UnmarshalECCPublicKey(object []byte) (pub ecdsa.PublicKey) {
var public ecdsa.PublicKey
rt := new(retrieve)
errmarsh := json.Unmarshal(object, &rt)
if errmarsh != nil {
fmt.Println("err at UnmarshalECCPublicKey()")
panic(errmarsh)
}
public.Curve = rt.Key.CurveParams
public.X = rt.Key.MyX
public.Y = rt.Key.MyY
mapstructure.Decode(public, &pub)
fmt.Println("Unmarshalled ECC public key : ", pub)
return
}
we will pass the the marshalled public key to UnmarshalECCPublicKey() and it will return the correct unmarshaled obj
so the coorect use will be :
var privateKey *ecdsa.PrivateKey
var publicKey ecdsa.PublicKey
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatalf("Failed to generate ECDSA key: %s\n", err)
}
publicKey = privateKey.PublicKey
marshalledKey, err := json.Marshal(publicKey)
if err != nil {
panic(err)
}
var unmarshalledKey ecdsa.PublicKey
unmarshalledKey = UnmarshalECCPublicKey(marshalledKey)
and that should do it, u will get the ECC public unmarshalled successfully.

How to validate a signature signed with PKCS8 private key?

I'm developing a program with Go language for validating signatures.
It receives parameters(public key, signature, plaintext)
and the signature is signed by user's private key in PKCS#8.
I tried to use the function VerifyPKCS1v15 in the package x509
but it didn't work for me.
I guess it may due to the function is oriented for signatures made by pkcs1 private keys.
can anybody help me?
I wanna know if there is any way to validate signatures using pkcs8 public key?
this is my code
func main() {
var plainTest = "P0000000025300000100000000001000026720180705140842"
var hashVal = "15b47c1d79b0be2aae36a05bcd8644af7bfe3dd4e0c23e2b78692fc900998fca"
var signatureStr = "WWFCZsD3BhakkCaLAcTPxMvd3Pom1Glhgcc+xhR7tIDBLvkVk/LtxV+2nHw6b9u0Dcla8U4vUR7KH8zpUS7fNJD9yPDDWxH5PYiw4jQTjziiLHSUpuaGbf8N1Y2jKPXvzq1ZFaEAqCirLSmt5KyD3gQ22ysHgYA2vH44zzBApcxYXVbzLbCIGAR5aL/mvYt7uWsh4FX8dQ49v9SqIm/rRBGEbsscF4HpQApy8VqRGvq6EbwrPCfMcpwIbBHdDUR0mneaNg9GH4hozfMC08SZtAMGDk8J/NQway1FisrjpUeZfMe/hANDH1LmfrbThKDgB7WIpDryCXMTsBKjrqyArQ=="
var pubKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA17hWIujBfiqrd4o0JCEn6N1mzv94VM9LiVHoldvPRDEwCXbeoSebzZElvhkJsPl08o68g1BgRC4LpaGQDcVzwyFMs4DnXEDLapZQpTzkmXaSIYIRYER/U1OgdW5Cq2do/eTrylWdloqWuz5JL2vIr4GFycnEduYVSzFmAqucCvgGEFUxwFxtZ95BVsxfKOt7eFCJWoS0iR2/If5EMG9F6KG6DtDUWg6awN2mIbhm8fqxSF48ehCkPCN4s4YkcUlkmGYEetdBCxbaUh9/S960XjQBK3MXbLIJLgRLoEAdWJ2v6IjaEsw7dQAaMti3QOPr0x7TyHlS7rz/lyjlJjaXEQIDAQAB"
publicKeyBase64, err := base64.StdEncoding.DecodeString(pubKeyStr)
if err != nil {
fmt.Println("base64 error : " + err.Error())
}
fmt.Println("publicKeyBase64: ")
fmt.Println(string(publicKeyBase64))
pub, err := x509.ParsePKIXPublicKey(publicKeyBase64)
if err != nil {
fmt.Println("failed to parse DER encoded public key: " + err.Error())
}
switch pub := pub.(type) {
case *rsa.PublicKey:
fmt.Println("pub is of type RSA:", pub)
case *dsa.PublicKey:
fmt.Println("pub is of type DSA:", pub)
case *ecdsa.PublicKey:
fmt.Println("pub is of type ECDSA:", pub)
default:
panic("unknown type of public key")
}
publicKey, isRSAPublicKey := pub.(*rsa.PublicKey)
if !isRSAPublicKey {
fmt.Println("Public key parsed is not an RSA public key")
}
signatureBytes, _ := hex.DecodeString(signatureStr)
fmt.Println("signatureBytes : " + string(signatureBytes))
validateBytes := sha256.Sum256([]byte(plainTest))
fmt.Println("validateBytes : " + string(validateBytes[:]))
err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, validateBytes[:], signatureBytes)
if err != nil {
fmt.Printf("err: %v\n", err)
} else {
fmt.Printf("ok")
}
}
I got the same problem, it turns out my publicKey is wrong.
I mean not the format, but the key is not paired with the private key.
I change to another pair of key, and the code worked.

SQL query results to go inside a nested struct, using Golang

Below is the whole code of the program. It is a service that forwards requests. Currently working. What I am trying to do is get rid of the yml file that is currently storing all configs and move them to db. I don't want to mess with the code much, so my idea was to simply store the db data in the same structs.
// Config contains configuration for this service
type Instance struct {
User string `json:"user"`
Password string `json:"password"`
InstanceId string `json:"instance_id"`
InstanceType string `json:"instance_type"`
InstanceMode string `json:"instance_mode"`
ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"`
PublicKey string `json:"pubkey"`
Apis Api `json:"apis"`
}
// API struct
type Api struct {
Name string `json:"name"`
Url string `json:"url"`
Version string `json:"version"`
IsBhdGw bool `json:"isBhdGw"`
Key string `json:"key"`
}
// API struc
type InfoResponse struct {
InstanceId string `json:"instance_id"`
InstanceType string `json:"instance_type"`
InstanceMode string `json:"instance_mode"`
ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"`
PublicKey string `json:"pubkey"`
Apis Api `json:"apis"`
}
type Settings struct {
Port int `json:"port"`
User string `json:"user"`
Secret string `json:"secret"`
Mode string `json:"mode"`
}
type Instances struct {
Instances []Instance
}
var payloadLength int = 3
var instances Instances
var settings Settings
var db *sql.DB
func fetchInstances() []Instance {
rows, err := db.Query("SELECT Instances.InstanceId, Instances.User, Instances.Password, Instances.InstanceType, Instances.InstanceMode, Instances.ClientId, Instances.ClientSecret, Instances.PublicKey, Api.Name, Api.Url, Api.Version, Api.IsBhdGw, Api.Key FROM Instances, Api")
if err != nil {
panic(err.Error())
}
defer rows.Close()
instances := []Instance{}
for rows.Next() {
var instance Instance
var apis Api
err := rows.Scan(&instance.InstanceId, &instance.User, &instance.Password,
&instance.InstanceType, &instance.InstanceMode, &instance.ClientId, &instance.ClientSecret, &instance.PublicKey,
&apis.Name, &apis.Url, &apis.Version, &apis.IsBhdGw, &apis.Key)
if err != nil {
panic(err.Error())
}
instance.Apis = apis
instances = append(instances, instance)
}
return instances
}
When I run this I get a "panic: runtime error: invalid memory address or nil pointer dereference"
You are attempting to connect to an uninitiated database connection. This is due to variable shadowing.
Although you've defined a global db variable:
var db *sql.DB
Your main() method creates a new one when it connects:
db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"#tcp(db:3306)/"+dbName)
So then when you call fetchInstances, which uses the global variable, the global one is still unset.
The easiest solution is to change your code in main() as follows:
var err error
db, err = sql.Open(dbDriver, dbUser+":"+dbPass+"#tcp(db:3306)/"+dbName)
But the better solution is to never use a global variable. Use the locally-defined variable in main, then pass that to fetchInstances.
As a side note: ALWAYS, ALWAYS check your errors. Twice in your code, you fail to check db connection errors, as in:
db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"#tcp(db:3306)/"+dbName)
err = db.Ping()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
If the connection fails, your db.Ping() call will likely panic. Instead, you should do:
db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"#tcp(db:3306)/"+dbName)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = db.Ping()
if err != nil {
fmt.Println(err)
os.Exit(1)
}

1 interface, 2 packages, same struct variable names but different json naming conventions

I am wondering if it is possible in the below scenario to be able to remove the two "Balance" structs in each package and just use the interface based "Balance" struct somehow for unmarshalling. The issue that I have is that the json structure that comes back from the individual api's for Balance is different so as of right now I am just converting the local Balance structs into the global interface based Balance struct and returning that. This method is not ideal especially for more complex but very similar functions that I have. I am sure there is a better way to do this but could not find anything similar. Thanks in advance.
//******************** API Inteface *****************************
//API Interface path: /global/interfaces/apiinterface/apiinterface.go && structs.go
// /global/interfaces/apiinterface/apiinterface.go
type APIInterface interface {
//.... other interface func(s)
GetBalance(account string) (balance Balance, err error)
}
// /global/interfaces/apiinterface/structs.go
type Balance struct{
Available float64
Unconfirmed float64
}
//******************** Library 1 *****************************
//Library 1 path: /library1/library1.go
type jsonResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Result json.RawMessage `json:"result"`
}
//Library 1 Balance struct /library1/structs.go
type Balance struct {
Available float64 `json:"available"` //json name difference <----------
Unconfirmed float64 `json:"unconfirmed"` //json name difference <----------
}
//Library 1 GetBalance /library1/library1.go
func (c *Library1) GetBalance(account string) (balance apiinterface.Balance, err error) {
r, err := c.client.do("getbalance", []interface{}{account})
if err != nil {
return
}
var response jsonResponse
if err = json.Unmarshal(r, &response); err != nil {
return
}
var tmpBalance Balance //library 1 Balance struct
err = json.Unmarshal(response.Result, &tmpBalance)
if err != nil{
return
}
//convert to global apiinterface struct
balance = apiinterface.Balance{
Available:tmpBalance.Available,
Unconfirmed:tmpBalance.Unconfirmed,
}
return
}
//******************** Library 2 *****************************
//Library 2 path: /library2/library2.go
type jsonResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Result json.RawMessage `json:"result"`
}
//Library 2 Balance struct
type Balance struct {
Available float64 `json:"total"` //json name difference <----------
Unconfirmed float64 `json:"pending"` //json name difference <----------
}
//Library 2 GetBalance
func (c *Library2) GetBalance(account string) (balance apiinterface.Balance, err error) {
r, err := c.client.do("getbalance", []interface{}{account})
if err != nil {
return
}
var response jsonResponse
if err = json.Unmarshal(r, &response); err != nil {
return
}
var tmpBalance Balance //library 2 Balance struct
err = json.Unmarshal(response.Result, &tmpBalance)
if err != nil{
return
}
//convert to global apiinterface struct
balance = apiinterface.Balance{
Available:tmpBalance.Available,
Unconfirmed:tmpBalance.Unconfirmed,
}
return
}
See if something like this does what you need:
package main
import (
"encoding/json"
"fmt"
)
type jsonResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Result Balance `json:"result"`
}
type Balance struct {
Available float64
Unconfirmed float64
}
func (b *Balance) UnmarshalJSON(data []byte) error {
m := map[string]float64{}
if err := json.Unmarshal(data, &m); err != nil {
return err
}
for k, v := range m {
if k == "available" || k == "total" {
b.Available = v
} else if k == "unconfirmed" || k == "pending" {
b.Unconfirmed = v
}
}
return nil
}
func main() {
tests := []string{
`{"success":true,"message":"first","result":{"available":42.42,"unconfirmed":0.88}}`,
`{"success":true,"message":"second","result":{"total":3.14,"pending":0.42}}`,
}
for _, t := range tests {
resp := jsonResponse{}
if err := json.Unmarshal([]byte(t), &resp); err != nil {
panic(err)
}
fmt.Printf("%+v\n", resp)
}
}
playground
you can try somthing like this:
type Balance struct {
*Balance1
*Balance2
}
and then check them with nil, then cast the not nil one to your interface

golang decode JSON request in nested struct and insert in DB as blob

I have a nested struct which I am using to decode JSON request.
type Service struct {
ID string `json:"id,omitempty" db:"id"`
Name string `json:"name" db:"name"`
Contract struct {
ServiceTime int `json:"service_time"`
Region string `json:"region"`
} `json:"contract" db:"contract"`
}
I am using blob type to store Contract in MySQL. To make it work , I would be needing to create a different struct with Contract as string to insert in DB. Can this be done in better way by using single struct only or is there any other elegant way ?
This depends on what you use to talk to the database, but if you're using database/sql and a driver that provides support for this you can have your Contract type implement the Valuer interface.
type Service struct {
ID string `json:"id,omitempty" db:"id"`
Name string `json:"name" db:"name"`
Contract Contract `json:"contract" db:"contract"`
}
type Contract struct {
ServiceTime int `json:"service_time"`
Region string `json:"region"`
}
func (c *Contract) Value() (driver.Value, error) {
if c != nil {
b, err := json.Marshal(c)
if err != nil {
return nil, err
}
return string(b), nil
}
return nil, nil
}
And then when you're executing the query just pass in the Service.Contract field and the driver should call the Value method.
sql := // INSERT INTO ...
svc := // &Service{ ...
db.Exec(sql, svc.ID, svc.Name, svc.Contract)
And to be able to retrieve the blob back from db and unmarshal it back into Contract you can have it implement the Scanner interface, again, if a type implements this the driver is expected to call it.
func (c *Contract) Scan(src interface{}) error {
var data []byte
if b, ok := src.([]byte); ok {
data = b
} else if s, ok := src.(string); ok {
data = []byte(s)
}
return json.Unmarshal(data, c)
}
// ...
sql := // SELECT * FROM ...
svc := // &Service{ ...
db.QueryRow(sql, 123).Scan(&svc.ID, &svc.Name, &svc.Contract)