diff options
author | Determinant <[email protected]> | 2020-08-13 21:11:56 -0400 |
---|---|---|
committer | Determinant <[email protected]> | 2020-08-13 21:11:56 -0400 |
commit | 88cc3698b3663972cd9b60faf5c14a7e1bbee965 (patch) | |
tree | aafa80495750987f144607bd4b71154a365e7a3b /plugin/evm/service.go | |
parent | 1bb314f767785fe617c3c5efeca1a64127339506 (diff) |
WIP: X-to-C transfer
Diffstat (limited to 'plugin/evm/service.go')
-rw-r--r-- | plugin/evm/service.go | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/plugin/evm/service.go b/plugin/evm/service.go index 62b124f..75e7c31 100644 --- a/plugin/evm/service.go +++ b/plugin/evm/service.go @@ -8,10 +8,14 @@ import ( "crypto/rand" "fmt" "math/big" + "net/http" + "strings" "github.com/ava-labs/coreth" "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/gecko/api" + "github.com/ava-labs/gecko/utils/constants" "github.com/ava-labs/go-ethereum/common" "github.com/ava-labs/go-ethereum/common/hexutil" "github.com/ava-labs/go-ethereum/crypto" @@ -36,6 +40,8 @@ type SnowmanAPI struct{ vm *VM } // NetAPI offers network related API methods type NetAPI struct{ vm *VM } +type AvaAPI struct{ vm *VM } + // NewNetAPI creates a new net API instance. func NewNetAPI(vm *VM) *NetAPI { return &NetAPI{vm} } @@ -120,3 +126,106 @@ func (api *DebugAPI) IssueBlock(ctx context.Context) error { return api.vm.tryBlockGen() } + +// ExportKeyArgs are arguments for ExportKey +type ExportKeyArgs struct { + api.UserPass + Address string `json:"address"` +} + +// ExportKeyReply is the response for ExportKey +type ExportKeyReply struct { + // The decrypted PrivateKey for the Address provided in the arguments + PrivateKey string `json:"privateKey"` +} + +// ExportKey returns a private key from the provided user +func (service *AvaAPI) ExportKey(r *http.Request, args *ExportKeyArgs, reply *ExportKeyReply) error { + service.vm.ctx.Log.Info("Platform: ExportKey called") + db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password) + if err != nil { + return fmt.Errorf("problem retrieving user '%s': %w", args.Username, err) + } + user := user{db: db} + if address, err := service.vm.ParseAddress(args.Address); err != nil { + return fmt.Errorf("couldn't parse %s to address: %s", args.Address, err) + } else if sk, err := user.getKey(address); err != nil { + return fmt.Errorf("problem retrieving private key: %w", err) + } else { + reply.PrivateKey = common.ToHex(crypto.FromECDSA(sk)) + //constants.SecretKeyPrefix + formatting.CB58{Bytes: sk.Bytes()}.String() + return nil + } +} + +// ImportKeyArgs are arguments for ImportKey +type ImportKeyArgs struct { + api.UserPass + PrivateKey string `json:"privateKey"` +} + +// ImportKey adds a private key to the provided user +func (service *AvaAPI) ImportKey(r *http.Request, args *ImportKeyArgs, reply *api.JsonAddress) error { + service.vm.ctx.Log.Info("Platform: ImportKey called for user '%s'", args.Username) + db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password) + if err != nil { + return fmt.Errorf("problem retrieving data: %w", err) + } + + user := user{db: db} + + if !strings.HasPrefix(args.PrivateKey, constants.SecretKeyPrefix) { + return fmt.Errorf("private key missing %s prefix", constants.SecretKeyPrefix) + } + sk, err := crypto.ToECDSA(common.FromHex(args.PrivateKey)) + if err != nil { + return fmt.Errorf("invalid private key") + } + if err = user.putAddress(sk); err != nil { + return fmt.Errorf("problem saving key %w", err) + } + + reply.Address, err = service.vm.FormatAddress(crypto.PubkeyToAddress(sk.PublicKey)) + if err != nil { + return fmt.Errorf("problem formatting address: %w", err) + } + return nil +} + +// ImportAVAArgs are the arguments to ImportAVA +type ImportAVAArgs struct { + api.UserPass + // The address that will receive the imported funds + To string `json:"to"` +} + +// ImportAVA returns an unsigned transaction to import AVA from the X-Chain. +// The AVA must have already been exported from the X-Chain. +func (service *AvaAPI) ImportAVA(_ *http.Request, args *ImportAVAArgs, response *api.JsonTxID) error { + service.vm.ctx.Log.Info("Platform: ImportAVA called") + + // Get the user's info + db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password) + if err != nil { + return fmt.Errorf("couldn't get user '%s': %w", args.Username, err) + } + user := user{db: db} + + to, err := service.vm.ParseAddress(args.To) + if err != nil { // Parse address + return fmt.Errorf("couldn't parse argument 'to' to an address: %w", err) + } + + privKeys, err := user.getKeys() + if err != nil { // Get keys + return fmt.Errorf("couldn't get keys controlled by the user: %w", err) + } + + tx, err := service.vm.newImportTx(to, privKeys) + if err != nil { + return err + } + + response.TxID = tx.ID() + return service.vm.issueTx(tx) +} |