2016-06-15 13:54:07 +00:00
|
|
|
package main
|
|
|
|
|
2018-09-24 18:07:34 +00:00
|
|
|
// #include <stdlib.h>
|
2016-06-15 19:50:35 +00:00
|
|
|
import "C"
|
2016-06-15 13:54:07 +00:00
|
|
|
import (
|
2019-02-15 11:31:20 +00:00
|
|
|
"encoding/hex"
|
2016-06-22 18:56:27 +00:00
|
|
|
"encoding/json"
|
2019-03-04 14:33:48 +00:00
|
|
|
"errors"
|
2016-06-15 13:54:07 +00:00
|
|
|
"fmt"
|
2016-07-27 11:47:41 +00:00
|
|
|
"os"
|
2018-06-27 23:16:27 +00:00
|
|
|
"unsafe"
|
2016-09-11 11:44:14 +00:00
|
|
|
|
2020-01-02 09:10:19 +00:00
|
|
|
validator "gopkg.in/go-playground/validator.v9"
|
|
|
|
|
2018-06-19 07:49:24 +00:00
|
|
|
"github.com/status-im/status-go/api"
|
2019-11-23 17:57:05 +00:00
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
2019-03-04 14:33:48 +00:00
|
|
|
"github.com/status-im/status-go/exportlogs"
|
2018-04-22 16:50:34 +00:00
|
|
|
"github.com/status-im/status-go/logutils"
|
2019-08-20 15:38:40 +00:00
|
|
|
"github.com/status-im/status-go/multiaccounts"
|
|
|
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
2018-06-08 11:29:50 +00:00
|
|
|
"github.com/status-im/status-go/params"
|
2018-02-02 12:23:47 +00:00
|
|
|
"github.com/status-im/status-go/profiling"
|
2019-11-21 16:19:22 +00:00
|
|
|
protocol "github.com/status-im/status-go/protocol"
|
2018-08-16 11:37:53 +00:00
|
|
|
"github.com/status-im/status-go/services/personal"
|
2018-11-06 06:26:12 +00:00
|
|
|
"github.com/status-im/status-go/services/typeddata"
|
2018-06-27 23:16:27 +00:00
|
|
|
"github.com/status-im/status-go/signal"
|
2018-08-16 11:37:53 +00:00
|
|
|
"github.com/status-im/status-go/transactions"
|
2016-06-15 13:54:07 +00:00
|
|
|
)
|
|
|
|
|
2019-08-20 15:38:40 +00:00
|
|
|
// OpenAccounts opens database and returns accounts list.
|
|
|
|
//export OpenAccounts
|
|
|
|
func OpenAccounts(datadir *C.char) *C.char {
|
|
|
|
statusBackend.UpdateRootDataDir(C.GoString(datadir))
|
|
|
|
err := statusBackend.OpenAccounts()
|
2017-05-16 12:09:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2019-08-20 15:38:40 +00:00
|
|
|
accs, err := statusBackend.GetAccounts()
|
|
|
|
if err != nil {
|
2018-04-22 16:50:34 +00:00
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2019-08-20 15:38:40 +00:00
|
|
|
data, err := json.Marshal(accs)
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
return C.CString(string(data))
|
2017-05-25 13:14:52 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 08:05:32 +00:00
|
|
|
// ExtractGroupMembershipSignatures extract public keys from tuples of content/signature
|
|
|
|
//export ExtractGroupMembershipSignatures
|
|
|
|
func ExtractGroupMembershipSignatures(signaturePairsStr *C.char) *C.char {
|
|
|
|
var signaturePairs [][2]string
|
2018-09-27 13:07:32 +00:00
|
|
|
|
|
|
|
if err := json.Unmarshal([]byte(C.GoString(signaturePairsStr)), &signaturePairs); err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
2018-11-06 08:05:32 +00:00
|
|
|
identities, err := statusBackend.ExtractGroupMembershipSignatures(signaturePairs)
|
|
|
|
if err != nil {
|
2018-09-27 13:07:32 +00:00
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
2018-09-28 11:53:36 +00:00
|
|
|
data, err := json.Marshal(struct {
|
2018-11-06 08:05:32 +00:00
|
|
|
Identities []string `json:"identities"`
|
|
|
|
}{Identities: identities})
|
2018-09-28 11:53:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return C.CString(string(data))
|
2018-09-27 13:07:32 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 08:05:32 +00:00
|
|
|
// Sign signs a string containing group membership information
|
|
|
|
//export SignGroupMembership
|
|
|
|
func SignGroupMembership(content *C.char) *C.char {
|
|
|
|
signature, err := statusBackend.SignGroupMembership(C.GoString(content))
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2018-10-04 16:53:48 +00:00
|
|
|
|
2018-11-06 08:05:32 +00:00
|
|
|
data, err := json.Marshal(struct {
|
|
|
|
Signature string `json:"signature"`
|
|
|
|
}{Signature: signature})
|
|
|
|
if err != nil {
|
2018-10-04 16:53:48 +00:00
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
2018-11-06 08:05:32 +00:00
|
|
|
return C.CString(string(data))
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//ValidateNodeConfig validates config for status node
|
2017-08-10 15:31:29 +00:00
|
|
|
//export ValidateNodeConfig
|
|
|
|
func ValidateNodeConfig(configJSON *C.char) *C.char {
|
2018-03-29 09:20:55 +00:00
|
|
|
var resp APIDetailedResponse
|
2017-08-10 15:31:29 +00:00
|
|
|
|
2018-09-13 16:31:29 +00:00
|
|
|
_, err := params.NewConfigFromJSON(C.GoString(configJSON))
|
2017-08-10 15:31:29 +00:00
|
|
|
|
2018-03-29 09:20:55 +00:00
|
|
|
// Convert errors to APIDetailedResponse
|
2017-08-10 15:31:29 +00:00
|
|
|
switch err := err.(type) {
|
|
|
|
case validator.ValidationErrors:
|
2018-03-29 09:20:55 +00:00
|
|
|
resp = APIDetailedResponse{
|
2017-08-10 15:31:29 +00:00
|
|
|
Message: "validation: validation failed",
|
2018-03-29 09:20:55 +00:00
|
|
|
FieldErrors: make([]APIFieldError, len(err)),
|
2017-08-10 15:31:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, ve := range err {
|
2018-03-29 09:20:55 +00:00
|
|
|
resp.FieldErrors[i] = APIFieldError{
|
2017-08-10 15:31:29 +00:00
|
|
|
Parameter: ve.Namespace(),
|
2018-03-29 09:20:55 +00:00
|
|
|
Errors: []APIError{
|
2017-08-10 15:31:29 +00:00
|
|
|
{
|
|
|
|
Message: fmt.Sprintf("field validation failed on the '%s' tag", ve.Tag()),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case error:
|
2018-03-29 09:20:55 +00:00
|
|
|
resp = APIDetailedResponse{
|
2017-08-10 15:31:29 +00:00
|
|
|
Message: fmt.Sprintf("validation: %s", err.Error()),
|
|
|
|
}
|
|
|
|
case nil:
|
2018-03-29 09:20:55 +00:00
|
|
|
resp = APIDetailedResponse{
|
2017-08-10 15:31:29 +00:00
|
|
|
Status: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
respJSON, err := json.Marshal(resp)
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return C.CString(string(respJSON))
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//ResetChainData remove chain data from data directory
|
2017-05-25 13:14:52 +00:00
|
|
|
//export ResetChainData
|
|
|
|
func ResetChainData() *C.char {
|
2018-06-19 07:49:24 +00:00
|
|
|
api.RunAsync(statusBackend.ResetChainData)
|
2018-02-09 13:37:56 +00:00
|
|
|
return makeJSONResponse(nil)
|
2017-05-16 12:09:52 +00:00
|
|
|
}
|
|
|
|
|
2018-04-16 08:01:37 +00:00
|
|
|
//CallRPC calls public APIs via RPC
|
2017-05-28 13:57:30 +00:00
|
|
|
//export CallRPC
|
|
|
|
func CallRPC(inputJSON *C.char) *C.char {
|
2018-12-20 08:31:17 +00:00
|
|
|
outputJSON, err := statusBackend.CallRPC(C.GoString(inputJSON))
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2017-05-28 13:57:30 +00:00
|
|
|
return C.CString(outputJSON)
|
|
|
|
}
|
|
|
|
|
2018-04-16 08:01:37 +00:00
|
|
|
//CallPrivateRPC calls both public and private APIs via RPC
|
|
|
|
//export CallPrivateRPC
|
|
|
|
func CallPrivateRPC(inputJSON *C.char) *C.char {
|
2018-12-20 08:31:17 +00:00
|
|
|
outputJSON, err := statusBackend.CallPrivateRPC(C.GoString(inputJSON))
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2018-04-16 08:01:37 +00:00
|
|
|
return C.CString(outputJSON)
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//CreateAccount is equivalent to creating an account from the command line,
|
|
|
|
// just modified to handle the function arg passing
|
2016-06-29 11:32:04 +00:00
|
|
|
//export CreateAccount
|
2016-07-01 13:23:39 +00:00
|
|
|
func CreateAccount(password *C.char) *C.char {
|
2019-01-18 09:01:14 +00:00
|
|
|
info, mnemonic, err := statusBackend.AccountManager().CreateAccount(C.GoString(password))
|
2016-06-30 13:23:07 +00:00
|
|
|
|
2016-09-11 11:44:14 +00:00
|
|
|
errString := ""
|
2016-06-30 13:23:07 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
errString = err.Error()
|
|
|
|
}
|
|
|
|
|
2018-03-29 09:20:55 +00:00
|
|
|
out := AccountInfo{
|
2019-01-18 09:01:14 +00:00
|
|
|
Address: info.WalletAddress,
|
|
|
|
PubKey: info.WalletPubKey,
|
|
|
|
WalletAddress: info.WalletAddress,
|
|
|
|
WalletPubKey: info.WalletPubKey,
|
|
|
|
ChatAddress: info.ChatAddress,
|
|
|
|
ChatPubKey: info.ChatPubKey,
|
|
|
|
Mnemonic: mnemonic,
|
|
|
|
Error: errString,
|
2016-08-18 00:15:58 +00:00
|
|
|
}
|
2017-10-18 20:03:05 +00:00
|
|
|
outBytes, _ := json.Marshal(out)
|
2016-08-18 00:15:58 +00:00
|
|
|
return C.CString(string(outBytes))
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//RecoverAccount re-creates master key using given details
|
2016-08-24 15:10:42 +00:00
|
|
|
//export RecoverAccount
|
|
|
|
func RecoverAccount(password, mnemonic *C.char) *C.char {
|
2019-01-18 09:01:14 +00:00
|
|
|
info, err := statusBackend.AccountManager().RecoverAccount(C.GoString(password), C.GoString(mnemonic))
|
2016-08-18 00:15:58 +00:00
|
|
|
|
2016-09-11 11:44:14 +00:00
|
|
|
errString := ""
|
2016-08-18 00:15:58 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
errString = err.Error()
|
|
|
|
}
|
|
|
|
|
2018-03-29 09:20:55 +00:00
|
|
|
out := AccountInfo{
|
2019-01-18 09:01:14 +00:00
|
|
|
Address: info.WalletAddress,
|
|
|
|
PubKey: info.WalletPubKey,
|
|
|
|
WalletAddress: info.WalletAddress,
|
|
|
|
WalletPubKey: info.WalletPubKey,
|
|
|
|
ChatAddress: info.ChatAddress,
|
|
|
|
ChatPubKey: info.ChatPubKey,
|
|
|
|
Mnemonic: C.GoString(mnemonic),
|
|
|
|
Error: errString,
|
2016-06-15 13:54:07 +00:00
|
|
|
}
|
2017-10-18 20:03:05 +00:00
|
|
|
outBytes, _ := json.Marshal(out)
|
2016-06-30 13:23:07 +00:00
|
|
|
return C.CString(string(outBytes))
|
2016-06-15 13:54:07 +00:00
|
|
|
}
|
2016-06-20 15:21:45 +00:00
|
|
|
|
2019-06-26 22:28:16 +00:00
|
|
|
// StartOnboarding initialize the onboarding with n random accounts
|
|
|
|
//export StartOnboarding
|
|
|
|
func StartOnboarding(n, mnemonicPhraseLength C.int) *C.char {
|
|
|
|
out := struct {
|
|
|
|
Accounts []OnboardingAccount `json:"accounts"`
|
|
|
|
Error string `json:"error"`
|
|
|
|
}{
|
|
|
|
Accounts: make([]OnboardingAccount, 0),
|
|
|
|
}
|
|
|
|
|
|
|
|
accounts, err := statusBackend.AccountManager().StartOnboarding(int(n), int(mnemonicPhraseLength))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
out.Error = err.Error()
|
|
|
|
}
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
for _, account := range accounts {
|
|
|
|
out.Accounts = append(out.Accounts, OnboardingAccount{
|
|
|
|
ID: account.ID,
|
|
|
|
Address: account.Info.WalletAddress,
|
|
|
|
PubKey: account.Info.WalletPubKey,
|
|
|
|
WalletAddress: account.Info.WalletAddress,
|
|
|
|
WalletPubKey: account.Info.WalletPubKey,
|
|
|
|
ChatAddress: account.Info.ChatAddress,
|
|
|
|
ChatPubKey: account.Info.ChatPubKey,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
outBytes, _ := json.Marshal(out)
|
|
|
|
return C.CString(string(outBytes))
|
|
|
|
}
|
|
|
|
|
|
|
|
// ImportOnboardingAccount re-creates and imports an account created during onboarding.
|
|
|
|
//export ImportOnboardingAccount
|
|
|
|
func ImportOnboardingAccount(id, password *C.char) *C.char {
|
|
|
|
info, mnemonic, err := statusBackend.AccountManager().ImportOnboardingAccount(C.GoString(id), C.GoString(password))
|
|
|
|
|
|
|
|
errString := ""
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
errString = err.Error()
|
|
|
|
}
|
|
|
|
|
|
|
|
out := AccountInfo{
|
|
|
|
Address: info.WalletAddress,
|
|
|
|
PubKey: info.WalletPubKey,
|
|
|
|
WalletAddress: info.WalletAddress,
|
|
|
|
WalletPubKey: info.WalletPubKey,
|
|
|
|
ChatAddress: info.ChatAddress,
|
|
|
|
ChatPubKey: info.ChatPubKey,
|
|
|
|
Mnemonic: mnemonic,
|
|
|
|
Error: errString,
|
|
|
|
}
|
|
|
|
outBytes, _ := json.Marshal(out)
|
|
|
|
return C.CString(string(outBytes))
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveOnboarding resets the current onboarding removing from memory all the generated keys.
|
|
|
|
//export RemoveOnboarding
|
|
|
|
func RemoveOnboarding() {
|
|
|
|
statusBackend.AccountManager().RemoveOnboarding()
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//VerifyAccountPassword verifies account password
|
2017-05-06 21:53:18 +00:00
|
|
|
//export VerifyAccountPassword
|
2017-05-15 21:49:22 +00:00
|
|
|
func VerifyAccountPassword(keyStoreDir, address, password *C.char) *C.char {
|
2018-06-19 07:49:24 +00:00
|
|
|
_, err := statusBackend.AccountManager().VerifyAccountPassword(C.GoString(keyStoreDir), C.GoString(address), C.GoString(password))
|
2017-05-16 12:09:52 +00:00
|
|
|
return makeJSONResponse(err)
|
2017-05-06 21:53:18 +00:00
|
|
|
}
|
|
|
|
|
2019-08-20 15:38:40 +00:00
|
|
|
//StartNode - start Status node
|
|
|
|
//export StartNode
|
|
|
|
func StartNode(configJSON *C.char) *C.char {
|
|
|
|
config, err := params.NewConfigFromJSON(C.GoString(configJSON))
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := logutils.OverrideRootLogWithConfig(config, false); err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
api.RunAsync(func() error { return statusBackend.StartNode(config) })
|
|
|
|
return makeJSONResponse(nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
//StopNode - stop status node
|
|
|
|
//export StopNode
|
|
|
|
func StopNode() *C.char {
|
|
|
|
api.RunAsync(statusBackend.StopNode)
|
|
|
|
return makeJSONResponse(nil)
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//Login loads a key file (for a given address), tries to decrypt it using the password, to verify ownership
|
|
|
|
// if verified, purges all the previous identities from Whisper, and injects verified key as shh identity
|
2016-06-29 11:32:04 +00:00
|
|
|
//export Login
|
2019-08-20 15:38:40 +00:00
|
|
|
func Login(accountData, password *C.char) *C.char {
|
|
|
|
data, pass := C.GoString(accountData), C.GoString(password)
|
|
|
|
var account multiaccounts.Account
|
|
|
|
err := json.Unmarshal([]byte(data), &account)
|
2019-07-26 14:45:10 +00:00
|
|
|
if err != nil {
|
2019-08-20 15:38:40 +00:00
|
|
|
return makeJSONResponse(err)
|
2019-07-26 14:45:10 +00:00
|
|
|
}
|
2019-08-20 15:38:40 +00:00
|
|
|
api.RunAsync(func() error { return statusBackend.StartNodeWithAccount(account, pass) })
|
|
|
|
return makeJSONResponse(nil)
|
|
|
|
}
|
2019-07-26 14:45:10 +00:00
|
|
|
|
2019-08-20 15:38:40 +00:00
|
|
|
// SaveAccountAndLogin saves account in status-go database..
|
|
|
|
//export SaveAccountAndLogin
|
2019-12-27 09:58:25 +00:00
|
|
|
func SaveAccountAndLogin(accountData, password, settingsJSON, configJSON, subaccountData *C.char) *C.char {
|
|
|
|
data, setJSON, confJSON, subData := C.GoString(accountData), C.GoString(settingsJSON), C.GoString(configJSON), C.GoString(subaccountData)
|
2019-08-20 15:38:40 +00:00
|
|
|
var account multiaccounts.Account
|
|
|
|
err := json.Unmarshal([]byte(data), &account)
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2019-12-27 09:58:25 +00:00
|
|
|
var settings accounts.Settings
|
|
|
|
err = json.Unmarshal([]byte(setJSON), &settings)
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
var conf params.NodeConfig
|
2019-08-20 15:38:40 +00:00
|
|
|
err = json.Unmarshal([]byte(confJSON), &conf)
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
var subaccs []accounts.Account
|
|
|
|
err = json.Unmarshal([]byte(subData), &subaccs)
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2020-02-10 11:22:37 +00:00
|
|
|
err = statusBackend.StartNodeWithAccountAndConfig(account, C.GoString(password), settings, &conf, subaccs)
|
2019-12-27 09:58:25 +00:00
|
|
|
return makeJSONResponse(err)
|
2019-08-20 15:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// InitKeystore initialize keystore before doing any operations with keys.
|
|
|
|
//export InitKeystore
|
|
|
|
func InitKeystore(keydir *C.char) *C.char {
|
|
|
|
err := statusBackend.AccountManager().InitKeystore(C.GoString(keydir))
|
2017-05-16 12:09:52 +00:00
|
|
|
return makeJSONResponse(err)
|
2016-06-29 11:32:04 +00:00
|
|
|
}
|
|
|
|
|
2019-01-24 15:44:46 +00:00
|
|
|
// LoginWithKeycard initializes an account with a chat key and encryption key used for PFS.
|
|
|
|
// It purges all the previous identities from Whisper, and injects the key as shh identity.
|
|
|
|
//export LoginWithKeycard
|
|
|
|
func LoginWithKeycard(chatKeyData, encryptionKeyData *C.char) *C.char {
|
|
|
|
err := statusBackend.InjectChatAccount(C.GoString(chatKeyData), C.GoString(encryptionKeyData))
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//Logout is equivalent to clearing whisper identities
|
2016-08-29 00:31:16 +00:00
|
|
|
//export Logout
|
|
|
|
func Logout() *C.char {
|
2018-06-19 07:49:24 +00:00
|
|
|
err := statusBackend.Logout()
|
2019-08-20 15:38:40 +00:00
|
|
|
if err != nil {
|
|
|
|
makeJSONResponse(err)
|
|
|
|
}
|
2019-08-21 11:53:33 +00:00
|
|
|
return makeJSONResponse(statusBackend.StopNode())
|
2016-08-29 00:31:16 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 11:37:53 +00:00
|
|
|
// SignMessage unmarshals rpc params {data, address, password} and passes
|
|
|
|
// them onto backend.SignMessage
|
|
|
|
//export SignMessage
|
|
|
|
func SignMessage(rpcParams *C.char) *C.char {
|
|
|
|
var params personal.SignParams
|
|
|
|
err := json.Unmarshal([]byte(C.GoString(rpcParams)), ¶ms)
|
2017-09-04 12:56:58 +00:00
|
|
|
if err != nil {
|
2018-08-16 11:37:53 +00:00
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
2017-09-04 12:56:58 +00:00
|
|
|
}
|
2018-08-16 11:37:53 +00:00
|
|
|
result, err := statusBackend.SignMessage(params)
|
|
|
|
return C.CString(prepareJSONResponse(result.String(), err))
|
2016-11-05 17:12:24 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 11:37:53 +00:00
|
|
|
// Recover unmarshals rpc params {signDataString, signedData} and passes
|
|
|
|
// them onto backend.
|
|
|
|
//export Recover
|
|
|
|
func Recover(rpcParams *C.char) *C.char {
|
|
|
|
var params personal.RecoverParams
|
|
|
|
err := json.Unmarshal([]byte(C.GoString(rpcParams)), ¶ms)
|
2016-10-30 22:35:10 +00:00
|
|
|
if err != nil {
|
2018-08-16 11:37:53 +00:00
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
2017-09-04 12:56:58 +00:00
|
|
|
}
|
2018-08-16 11:37:53 +00:00
|
|
|
addr, err := statusBackend.Recover(params)
|
|
|
|
return C.CString(prepareJSONResponse(addr.String(), err))
|
2016-10-30 22:35:10 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 11:37:53 +00:00
|
|
|
// SendTransaction converts RPC args and calls backend.SendTransaction
|
|
|
|
//export SendTransaction
|
|
|
|
func SendTransaction(txArgsJSON, password *C.char) *C.char {
|
|
|
|
var params transactions.SendTxArgs
|
|
|
|
err := json.Unmarshal([]byte(C.GoString(txArgsJSON)), ¶ms)
|
2017-09-04 12:56:58 +00:00
|
|
|
if err != nil {
|
2018-08-16 11:37:53 +00:00
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
2016-11-05 17:12:24 +00:00
|
|
|
}
|
2018-08-16 11:37:53 +00:00
|
|
|
hash, err := statusBackend.SendTransaction(params, C.GoString(password))
|
|
|
|
code := codeUnknown
|
|
|
|
if c, ok := errToCodeMap[err]; ok {
|
|
|
|
code = c
|
2017-09-04 12:56:58 +00:00
|
|
|
}
|
2018-08-16 11:37:53 +00:00
|
|
|
return C.CString(prepareJSONResponseWithCode(hash.String(), err, code))
|
2016-11-05 17:12:24 +00:00
|
|
|
}
|
|
|
|
|
2019-02-15 11:31:20 +00:00
|
|
|
// SendTransactionWithSignature converts RPC args and calls backend.SendTransactionWithSignature
|
|
|
|
//export SendTransactionWithSignature
|
|
|
|
func SendTransactionWithSignature(txArgsJSON, sigString *C.char) *C.char {
|
|
|
|
var params transactions.SendTxArgs
|
|
|
|
err := json.Unmarshal([]byte(C.GoString(txArgsJSON)), ¶ms)
|
|
|
|
if err != nil {
|
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
|
|
|
}
|
|
|
|
|
|
|
|
sig, err := hex.DecodeString(C.GoString(sigString))
|
|
|
|
if err != nil {
|
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
|
|
|
}
|
|
|
|
|
|
|
|
hash, err := statusBackend.SendTransactionWithSignature(params, sig)
|
|
|
|
code := codeUnknown
|
|
|
|
if c, ok := errToCodeMap[err]; ok {
|
|
|
|
code = c
|
|
|
|
}
|
|
|
|
return C.CString(prepareJSONResponseWithCode(hash.String(), err, code))
|
|
|
|
}
|
|
|
|
|
2019-02-21 09:53:39 +00:00
|
|
|
// HashTransaction validate the transaction and returns new txArgs and the transaction hash.
|
|
|
|
//export HashTransaction
|
|
|
|
func HashTransaction(txArgsJSON *C.char) *C.char {
|
|
|
|
var params transactions.SendTxArgs
|
|
|
|
err := json.Unmarshal([]byte(C.GoString(txArgsJSON)), ¶ms)
|
|
|
|
if err != nil {
|
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
|
|
|
}
|
|
|
|
|
|
|
|
newTxArgs, hash, err := statusBackend.HashTransaction(params)
|
|
|
|
code := codeUnknown
|
|
|
|
if c, ok := errToCodeMap[err]; ok {
|
|
|
|
code = c
|
|
|
|
}
|
|
|
|
|
|
|
|
result := struct {
|
|
|
|
Transaction transactions.SendTxArgs `json:"transaction"`
|
2019-11-23 17:57:05 +00:00
|
|
|
Hash types.Hash `json:"hash"`
|
2019-02-21 09:53:39 +00:00
|
|
|
}{
|
|
|
|
Transaction: newTxArgs,
|
|
|
|
Hash: hash,
|
|
|
|
}
|
|
|
|
|
|
|
|
return C.CString(prepareJSONResponseWithCode(result, err, code))
|
|
|
|
}
|
|
|
|
|
2019-03-21 10:48:47 +00:00
|
|
|
// HashMessage calculates the hash of a message to be safely signed by the keycard
|
|
|
|
// The hash is calulcated as
|
|
|
|
// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).
|
|
|
|
// This gives context to the signed message and prevents signing of transactions.
|
|
|
|
//export HashMessage
|
2019-04-29 23:26:41 +00:00
|
|
|
func HashMessage(message *C.char) *C.char {
|
|
|
|
hash, err := api.HashMessage(C.GoString(message))
|
|
|
|
code := codeUnknown
|
|
|
|
if c, ok := errToCodeMap[err]; ok {
|
|
|
|
code = c
|
2019-03-21 10:48:47 +00:00
|
|
|
}
|
2019-04-29 23:26:41 +00:00
|
|
|
return C.CString(prepareJSONResponseWithCode(fmt.Sprintf("0x%x", hash), err, code))
|
2019-03-21 10:48:47 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 06:26:12 +00:00
|
|
|
// SignTypedData unmarshall data into TypedData, validate it and signs with selected account,
|
|
|
|
// if password matches selected account.
|
|
|
|
//export SignTypedData
|
2019-07-26 14:45:10 +00:00
|
|
|
func SignTypedData(data, address, password *C.char) *C.char {
|
2018-11-06 06:26:12 +00:00
|
|
|
var typed typeddata.TypedData
|
|
|
|
err := json.Unmarshal([]byte(C.GoString(data)), &typed)
|
|
|
|
if err != nil {
|
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
|
|
|
}
|
|
|
|
if err := typed.Validate(); err != nil {
|
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
|
|
|
}
|
2019-07-26 14:45:10 +00:00
|
|
|
result, err := statusBackend.SignTypedData(typed, C.GoString(address), C.GoString(password))
|
2018-11-06 06:26:12 +00:00
|
|
|
return C.CString(prepareJSONResponse(result.String(), err))
|
|
|
|
}
|
|
|
|
|
2019-03-28 14:56:21 +00:00
|
|
|
// HashTypedData unmarshalls data into TypedData, validates it and hashes it.
|
|
|
|
//export HashTypedData
|
|
|
|
func HashTypedData(data *C.char) *C.char {
|
|
|
|
var typed typeddata.TypedData
|
|
|
|
err := json.Unmarshal([]byte(C.GoString(data)), &typed)
|
|
|
|
if err != nil {
|
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
|
|
|
}
|
|
|
|
if err := typed.Validate(); err != nil {
|
|
|
|
return C.CString(prepareJSONResponseWithCode(nil, err, codeFailedParseParams))
|
|
|
|
}
|
|
|
|
result, err := statusBackend.HashTypedData(typed)
|
|
|
|
return C.CString(prepareJSONResponse(result.String(), err))
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//StartCPUProfile runs pprof for cpu
|
2017-09-01 14:09:11 +00:00
|
|
|
//export StartCPUProfile
|
|
|
|
func StartCPUProfile(dataDir *C.char) *C.char {
|
|
|
|
err := profiling.StartCPUProfile(C.GoString(dataDir))
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//StopCPUProfiling stops pprof for cpu
|
2017-09-01 14:09:11 +00:00
|
|
|
//export StopCPUProfiling
|
2017-10-20 09:06:22 +00:00
|
|
|
func StopCPUProfiling() *C.char { //nolint: deadcode
|
2017-09-01 14:09:11 +00:00
|
|
|
err := profiling.StopCPUProfile()
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:06:22 +00:00
|
|
|
//WriteHeapProfile starts pprof for heap
|
2017-09-01 14:09:11 +00:00
|
|
|
//export WriteHeapProfile
|
2017-10-20 09:06:22 +00:00
|
|
|
func WriteHeapProfile(dataDir *C.char) *C.char { //nolint: deadcode
|
2017-09-01 14:09:11 +00:00
|
|
|
err := profiling.WriteHeapFile(C.GoString(dataDir))
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
2017-05-16 12:09:52 +00:00
|
|
|
func makeJSONResponse(err error) *C.char {
|
2016-12-11 12:19:20 +00:00
|
|
|
errString := ""
|
|
|
|
if err != nil {
|
2019-12-27 09:58:25 +00:00
|
|
|
fmt.Fprintf(os.Stderr, "makeJSONResponse with an error: %v\n", err)
|
2016-12-11 12:19:20 +00:00
|
|
|
errString = err.Error()
|
|
|
|
}
|
|
|
|
|
2018-03-29 09:20:55 +00:00
|
|
|
out := APIResponse{
|
2016-12-11 12:19:20 +00:00
|
|
|
Error: errString,
|
|
|
|
}
|
2017-10-18 20:03:05 +00:00
|
|
|
outBytes, _ := json.Marshal(out)
|
2016-12-11 12:19:20 +00:00
|
|
|
|
|
|
|
return C.CString(string(outBytes))
|
|
|
|
}
|
2017-09-15 15:57:34 +00:00
|
|
|
|
2017-12-21 10:26:01 +00:00
|
|
|
// AddPeer adds an enode as a peer.
|
2017-12-04 16:21:02 +00:00
|
|
|
//export AddPeer
|
|
|
|
func AddPeer(enode *C.char) *C.char {
|
2018-06-19 07:49:24 +00:00
|
|
|
err := statusBackend.StatusNode().AddPeer(C.GoString(enode))
|
2017-12-04 16:21:02 +00:00
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2018-02-09 20:28:16 +00:00
|
|
|
|
|
|
|
// ConnectionChange handles network state changes as reported
|
|
|
|
// by ReactNative (see https://facebook.github.io/react-native/docs/netinfo.html)
|
2018-02-20 08:22:15 +00:00
|
|
|
//export ConnectionChange
|
2018-02-09 20:28:16 +00:00
|
|
|
func ConnectionChange(typ *C.char, expensive C.int) {
|
2018-06-19 07:49:24 +00:00
|
|
|
statusBackend.ConnectionChange(C.GoString(typ), expensive == 1)
|
2018-02-09 20:28:16 +00:00
|
|
|
}
|
2018-03-14 15:46:21 +00:00
|
|
|
|
|
|
|
// AppStateChange handles app state changes (background/foreground).
|
|
|
|
//export AppStateChange
|
|
|
|
func AppStateChange(state *C.char) {
|
2018-06-19 07:49:24 +00:00
|
|
|
statusBackend.AppStateChange(C.GoString(state))
|
2018-03-14 15:46:21 +00:00
|
|
|
}
|
2018-06-27 23:16:27 +00:00
|
|
|
|
2018-07-24 10:05:21 +00:00
|
|
|
// SetSignalEventCallback setup geth callback to notify about new signal
|
2018-06-27 23:16:27 +00:00
|
|
|
//export SetSignalEventCallback
|
|
|
|
func SetSignalEventCallback(cb unsafe.Pointer) {
|
|
|
|
signal.SetSignalEventCallback(cb)
|
|
|
|
}
|
2019-03-04 14:33:48 +00:00
|
|
|
|
|
|
|
// ExportNodeLogs reads current node log and returns content to a caller.
|
|
|
|
//export ExportNodeLogs
|
|
|
|
func ExportNodeLogs() *C.char {
|
|
|
|
node := statusBackend.StatusNode()
|
|
|
|
if node == nil {
|
|
|
|
return makeJSONResponse(errors.New("node is not running"))
|
|
|
|
}
|
|
|
|
config := node.Config()
|
|
|
|
if config == nil {
|
|
|
|
return makeJSONResponse(errors.New("config and log file are not available"))
|
|
|
|
}
|
|
|
|
data, err := json.Marshal(exportlogs.ExportFromBaseFile(config.LogFile))
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(fmt.Errorf("error marshalling to json: %v", err))
|
|
|
|
}
|
|
|
|
return C.CString(string(data))
|
|
|
|
}
|
2019-03-21 12:02:16 +00:00
|
|
|
|
|
|
|
// ChaosModeUpdate changes the URL of the upstream RPC client.
|
|
|
|
//export ChaosModeUpdate
|
|
|
|
func ChaosModeUpdate(on C.int) *C.char {
|
|
|
|
node := statusBackend.StatusNode()
|
|
|
|
if node == nil {
|
|
|
|
return makeJSONResponse(errors.New("node is not running"))
|
|
|
|
}
|
|
|
|
|
|
|
|
err := node.ChaosModeCheckRPCClientsUpstreamURL(on == 1)
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
2019-03-29 10:20:24 +00:00
|
|
|
|
|
|
|
// GetNodesFromContract returns a list of nodes from a contract
|
|
|
|
//export GetNodesFromContract
|
|
|
|
func GetNodesFromContract(rpcEndpoint *C.char, contractAddress *C.char) *C.char {
|
|
|
|
nodes, err := statusBackend.GetNodesFromContract(
|
|
|
|
C.GoString(rpcEndpoint),
|
|
|
|
C.GoString(contractAddress),
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := json.Marshal(struct {
|
|
|
|
Nodes []string `json:"result"`
|
|
|
|
}{Nodes: nodes})
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return C.CString(string(data))
|
|
|
|
}
|
2019-04-18 13:52:08 +00:00
|
|
|
|
|
|
|
// SignHash exposes vanilla ECDSA signing required for Swarm messages
|
|
|
|
//export SignHash
|
|
|
|
func SignHash(hexEncodedHash *C.char) *C.char {
|
|
|
|
hexEncodedSignature, err := statusBackend.SignHash(
|
|
|
|
C.GoString(hexEncodedHash),
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return makeJSONResponse(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return C.CString(hexEncodedSignature)
|
|
|
|
}
|
2019-09-26 07:01:17 +00:00
|
|
|
|
|
|
|
// GenerateAlias returns a 3 random name words given the pk string 0x prefixed
|
|
|
|
//export GenerateAlias
|
|
|
|
func GenerateAlias(pk string) *C.char {
|
|
|
|
// We ignore any error, empty string is considered an error
|
|
|
|
name, _ := protocol.GenerateAlias(pk)
|
|
|
|
return C.CString(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Identicon returns the base64 identicon
|
|
|
|
//export Identicon
|
|
|
|
func Identicon(pk string) *C.char {
|
|
|
|
// We ignore any error, empty string is considered an error
|
|
|
|
identicon, _ := protocol.Identicon(pk)
|
|
|
|
return C.CString(identicon)
|
|
|
|
}
|