From 88cc3698b3663972cd9b60faf5c14a7e1bbee965 Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 13 Aug 2020 21:11:56 -0400 Subject: WIP: X-to-C transfer --- plugin/evm/user.go | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 plugin/evm/user.go (limited to 'plugin/evm/user.go') diff --git a/plugin/evm/user.go b/plugin/evm/user.go new file mode 100644 index 0000000..651f202 --- /dev/null +++ b/plugin/evm/user.go @@ -0,0 +1,142 @@ +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package evm + +import ( + "errors" + + "crypto/ecdsa" + "github.com/ava-labs/gecko/database" + "github.com/ava-labs/gecko/ids" + "github.com/ava-labs/go-ethereum/common" + "github.com/ava-labs/go-ethereum/crypto" +) + +// Key in the database whose corresponding value is the list of +// addresses this user controls +var addressesKey = ids.Empty.Bytes() + +var ( + errDBNil = errors.New("db uninitialized") + errKeyNil = errors.New("key uninitialized") + errEmptyAddress = errors.New("address is empty") +) + +type user struct { + // This user's database, acquired from the keystore + db database.Database +} + +// Get the addresses controlled by this user +func (u *user) getAddresses() ([]common.Address, error) { + if u.db == nil { + return nil, errDBNil + } + + // If user has no addresses, return empty list + hasAddresses, err := u.db.Has(addressesKey) + if err != nil { + return nil, err + } + if !hasAddresses { + return nil, nil + } + + // User has addresses. Get them. + bytes, err := u.db.Get(addressesKey) + if err != nil { + return nil, err + } + addresses := []common.Address{} + if err := Codec.Unmarshal(bytes, &addresses); err != nil { + return nil, err + } + return addresses, nil +} + +// controlsAddress returns true iff this user controls the given address +func (u *user) controlsAddress(address common.Address) (bool, error) { + if u.db == nil { + return false, errDBNil + //} else if address.IsZero() { + // return false, errEmptyAddress + } + return u.db.Has(address.Bytes()) +} + +// putAddress persists that this user controls address controlled by [privKey] +func (u *user) putAddress(privKey *ecdsa.PrivateKey) error { + if privKey == nil { + return errKeyNil + } + + address := crypto.PubkeyToAddress(privKey.PublicKey) // address the privKey controls + controlsAddress, err := u.controlsAddress(address) + if err != nil { + return err + } + if controlsAddress { // user already controls this address. Do nothing. + return nil + } + + if err := u.db.Put(address.Bytes(), crypto.FromECDSA(privKey)); err != nil { // Address --> private key + return err + } + + addresses := make([]common.Address, 0) // Add address to list of addresses user controls + userHasAddresses, err := u.db.Has(addressesKey) + if err != nil { + return err + } + if userHasAddresses { // Get addresses this user already controls, if they exist + if addresses, err = u.getAddresses(); err != nil { + return err + } + } + addresses = append(addresses, address) + bytes, err := Codec.Marshal(addresses) + if err != nil { + return err + } + if err := u.db.Put(addressesKey, bytes); err != nil { + return err + } + return nil +} + +// Key returns the private key that controls the given address +func (u *user) getKey(address common.Address) (*ecdsa.PrivateKey, error) { + if u.db == nil { + return nil, errDBNil + //} else if address.IsZero() { + // return nil, errEmptyAddress + } + + bytes, err := u.db.Get(address.Bytes()) + if err != nil { + return nil, err + } + sk, err := crypto.ToECDSA(bytes) + if err != nil { + return nil, err + } + return sk, nil +} + +// Return all private keys controlled by this user +func (u *user) getKeys() ([]*ecdsa.PrivateKey, error) { + addrs, err := u.getAddresses() + if err != nil { + return nil, err + } + keys := make([]*ecdsa.PrivateKey, len(addrs)) + for i, addr := range addrs { + key, err := u.getKey(addr) + if err != nil { + return nil, err + } + keys[i] = key + } + return keys, nil +} -- cgit v1.2.3 From 0844c8c6919f6d98ebe8a9501360ef5bc362dff3 Mon Sep 17 00:00:00 2001 From: Determinant Date: Wed, 19 Aug 2020 01:25:20 -0400 Subject: catch up with the new P-Chain cross-chain impl --- plugin/evm/user.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'plugin/evm/user.go') diff --git a/plugin/evm/user.go b/plugin/evm/user.go index 651f202..5d7a037 100644 --- a/plugin/evm/user.go +++ b/plugin/evm/user.go @@ -5,12 +5,13 @@ package evm import ( "errors" + "fmt" - "crypto/ecdsa" "github.com/ava-labs/gecko/database" "github.com/ava-labs/gecko/ids" + "github.com/ava-labs/gecko/utils/crypto" "github.com/ava-labs/go-ethereum/common" - "github.com/ava-labs/go-ethereum/crypto" + ethcrypto "github.com/ava-labs/go-ethereum/crypto" ) // Key in the database whose corresponding value is the list of @@ -66,12 +67,13 @@ func (u *user) controlsAddress(address common.Address) (bool, error) { } // putAddress persists that this user controls address controlled by [privKey] -func (u *user) putAddress(privKey *ecdsa.PrivateKey) error { +func (u *user) putAddress(privKey *crypto.PrivateKeySECP256K1R) error { if privKey == nil { return errKeyNil } - address := crypto.PubkeyToAddress(privKey.PublicKey) // address the privKey controls + address := ethcrypto.PubkeyToAddress( + (*privKey.PublicKey().(*crypto.PublicKeySECP256K1R).ToECDSA())) // address the privKey controls controlsAddress, err := u.controlsAddress(address) if err != nil { return err @@ -80,7 +82,7 @@ func (u *user) putAddress(privKey *ecdsa.PrivateKey) error { return nil } - if err := u.db.Put(address.Bytes(), crypto.FromECDSA(privKey)); err != nil { // Address --> private key + if err := u.db.Put(address.Bytes(), privKey.Bytes()); err != nil { // Address --> private key return err } @@ -106,31 +108,35 @@ func (u *user) putAddress(privKey *ecdsa.PrivateKey) error { } // Key returns the private key that controls the given address -func (u *user) getKey(address common.Address) (*ecdsa.PrivateKey, error) { +func (u *user) getKey(address common.Address) (*crypto.PrivateKeySECP256K1R, error) { if u.db == nil { return nil, errDBNil //} else if address.IsZero() { // return nil, errEmptyAddress } + factory := crypto.FactorySECP256K1R{} bytes, err := u.db.Get(address.Bytes()) if err != nil { return nil, err } - sk, err := crypto.ToECDSA(bytes) + sk, err := factory.ToPrivateKey(bytes) if err != nil { return nil, err } - return sk, nil + if sk, ok := sk.(*crypto.PrivateKeySECP256K1R); ok { + return sk, nil + } + return nil, fmt.Errorf("expected private key to be type *crypto.PrivateKeySECP256K1R but is type %T", sk) } // Return all private keys controlled by this user -func (u *user) getKeys() ([]*ecdsa.PrivateKey, error) { +func (u *user) getKeys() ([]*crypto.PrivateKeySECP256K1R, error) { addrs, err := u.getAddresses() if err != nil { return nil, err } - keys := make([]*ecdsa.PrivateKey, len(addrs)) + keys := make([]*crypto.PrivateKeySECP256K1R, len(addrs)) for i, addr := range addrs { key, err := u.getKey(addr) if err != nil { -- cgit v1.2.3 From 40879ea67433b73b464bd8b012a9809fbb646cfd Mon Sep 17 00:00:00 2001 From: Determinant Date: Wed, 19 Aug 2020 23:34:12 -0400 Subject: WIP: C-to-X transfer --- plugin/evm/user.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'plugin/evm/user.go') diff --git a/plugin/evm/user.go b/plugin/evm/user.go index 5d7a037..fbf2981 100644 --- a/plugin/evm/user.go +++ b/plugin/evm/user.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/gecko/ids" "github.com/ava-labs/gecko/utils/crypto" "github.com/ava-labs/go-ethereum/common" - ethcrypto "github.com/ava-labs/go-ethereum/crypto" ) // Key in the database whose corresponding value is the list of @@ -72,8 +71,7 @@ func (u *user) putAddress(privKey *crypto.PrivateKeySECP256K1R) error { return errKeyNil } - address := ethcrypto.PubkeyToAddress( - (*privKey.PublicKey().(*crypto.PublicKeySECP256K1R).ToECDSA())) // address the privKey controls + address := GetEthAddress(privKey) // address the privKey controls controlsAddress, err := u.controlsAddress(address) if err != nil { return err -- cgit v1.2.3