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/user.go | |
parent | 1bb314f767785fe617c3c5efeca1a64127339506 (diff) |
WIP: X-to-C transfer
Diffstat (limited to 'plugin/evm/user.go')
-rw-r--r-- | plugin/evm/user.go | 142 |
1 files changed, 142 insertions, 0 deletions
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 +} |