diff options
author | Péter Szilágyi <peterke@gmail.com> | 2017-01-24 17:49:20 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2017-02-13 20:00:02 +0800 |
commit | 833e4d1319336fbb66fd8f1e473c24472d65b17b (patch) | |
tree | 74d45d86d0c59c19f0ff67831f04e0cad9776eef /mobile | |
parent | 564b60520c68a1f06171abd705c01946b932492f (diff) | |
download | go-tangerine-833e4d1319336fbb66fd8f1e473c24472d65b17b.tar go-tangerine-833e4d1319336fbb66fd8f1e473c24472d65b17b.tar.gz go-tangerine-833e4d1319336fbb66fd8f1e473c24472d65b17b.tar.bz2 go-tangerine-833e4d1319336fbb66fd8f1e473c24472d65b17b.tar.lz go-tangerine-833e4d1319336fbb66fd8f1e473c24472d65b17b.tar.xz go-tangerine-833e4d1319336fbb66fd8f1e473c24472d65b17b.tar.zst go-tangerine-833e4d1319336fbb66fd8f1e473c24472d65b17b.zip |
accounts, cmd, eth, internal, mobile, node: split account backends
Diffstat (limited to 'mobile')
-rw-r--r-- | mobile/accounts.go | 99 | ||||
-rw-r--r-- | mobile/android_test.go | 34 | ||||
-rw-r--r-- | mobile/types.go | 5 |
3 files changed, 82 insertions, 56 deletions
diff --git a/mobile/accounts.go b/mobile/accounts.go index 621be4d7a..897549a6b 100644 --- a/mobile/accounts.go +++ b/mobile/accounts.go @@ -24,24 +24,25 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" ) const ( // StandardScryptN is the N parameter of Scrypt encryption algorithm, using 256MB // memory and taking approximately 1s CPU time on a modern processor. - StandardScryptN = int(accounts.StandardScryptN) + StandardScryptN = int(keystore.StandardScryptN) // StandardScryptP is the P parameter of Scrypt encryption algorithm, using 256MB // memory and taking approximately 1s CPU time on a modern processor. - StandardScryptP = int(accounts.StandardScryptP) + StandardScryptP = int(keystore.StandardScryptP) // LightScryptN is the N parameter of Scrypt encryption algorithm, using 4MB // memory and taking approximately 100ms CPU time on a modern processor. - LightScryptN = int(accounts.LightScryptN) + LightScryptN = int(keystore.LightScryptN) // LightScryptP is the P parameter of Scrypt encryption algorithm, using 4MB // memory and taking approximately 100ms CPU time on a modern processor. - LightScryptP = int(accounts.LightScryptP) + LightScryptP = int(keystore.LightScryptP) ) // Account represents a stored key. @@ -79,57 +80,73 @@ func (a *Account) GetAddress() *Address { // GetFile retrieves the path of the file containing the account key. func (a *Account) GetFile() string { - return a.account.File + return a.account.URL } -// AccountManager manages a key storage directory on disk. -type AccountManager struct{ manager *accounts.Manager } +// KeyStore manages a key storage directory on disk. +type KeyStore struct{ keystore *keystore.KeyStore } -// NewAccountManager creates a manager for the given directory. -func NewAccountManager(keydir string, scryptN, scryptP int) *AccountManager { - return &AccountManager{manager: accounts.NewManager(keydir, scryptN, scryptP)} +// NewKeyStore creates a keystore for the given directory. +func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore { + return &KeyStore{keystore: keystore.NewKeyStore(keydir, scryptN, scryptP)} } // HasAddress reports whether a key with the given address is present. -func (am *AccountManager) HasAddress(address *Address) bool { - return am.manager.HasAddress(address.address) +func (ks *KeyStore) HasAddress(address *Address) bool { + return ks.keystore.HasAddress(address.address) } // GetAccounts returns all key files present in the directory. -func (am *AccountManager) GetAccounts() *Accounts { - return &Accounts{am.manager.Accounts()} +func (ks *KeyStore) GetAccounts() *Accounts { + return &Accounts{ks.keystore.Accounts()} } // DeleteAccount deletes the key matched by account if the passphrase is correct. // If a contains no filename, the address must match a unique key. -func (am *AccountManager) DeleteAccount(account *Account, passphrase string) error { - return am.manager.Delete(accounts.Account{ - Address: account.account.Address, - File: account.account.File, - }, passphrase) +func (ks *KeyStore) DeleteAccount(account *Account, passphrase string) error { + return ks.keystore.Delete(account.account, passphrase) } -// Sign calculates a ECDSA signature for the given hash. The produced signature +// SignHash calculates a ECDSA signature for the given hash. The produced signature // is in the [R || S || V] format where V is 0 or 1. -func (am *AccountManager) Sign(address *Address, hash []byte) (signature []byte, _ error) { - return am.manager.Sign(address.address, hash) +func (ks *KeyStore) SignHash(address *Address, hash []byte) (signature []byte, _ error) { + return ks.keystore.SignHash(accounts.Account{Address: address.address}, hash) } -// SignPassphrase signs hash if the private key matching the given address can +// SignTx signs the given transaction with the requested account. +func (ks *KeyStore) SignTx(account *Account, tx *Transaction, chainID *BigInt) (*Transaction, error) { + signed, err := ks.keystore.SignTx(account.account, tx.tx, chainID.bigint) + if err != nil { + return nil, err + } + return &Transaction{signed}, nil +} + +// SignHashPassphrase signs hash if the private key matching the given address can // be decrypted with the given passphrase. The produced signature is in the // [R || S || V] format where V is 0 or 1. -func (am *AccountManager) SignPassphrase(account *Account, passphrase string, hash []byte) (signature []byte, _ error) { - return am.manager.SignWithPassphrase(account.account, passphrase, hash) +func (ks *KeyStore) SignHashPassphrase(account *Account, passphrase string, hash []byte) (signature []byte, _ error) { + return ks.keystore.SignHashWithPassphrase(account.account, passphrase, hash) +} + +// SignTxPassphrase signs the transaction if the private key matching the +// given address can be decrypted with the given passphrase. +func (ks *KeyStore) SignTxPassphrase(account *Account, passphrase string, tx *Transaction, chainID *BigInt) (*Transaction, error) { + signed, err := ks.keystore.SignTxWithPassphrase(account.account, passphrase, tx.tx, chainID.bigint) + if err != nil { + return nil, err + } + return &Transaction{signed}, nil } // Unlock unlocks the given account indefinitely. -func (am *AccountManager) Unlock(account *Account, passphrase string) error { - return am.manager.TimedUnlock(account.account, passphrase, 0) +func (ks *KeyStore) Unlock(account *Account, passphrase string) error { + return ks.keystore.TimedUnlock(account.account, passphrase, 0) } // Lock removes the private key with the given address from memory. -func (am *AccountManager) Lock(address *Address) error { - return am.manager.Lock(address.address) +func (ks *KeyStore) Lock(address *Address) error { + return ks.keystore.Lock(address.address) } // TimedUnlock unlocks the given account with the passphrase. The account stays @@ -139,14 +156,14 @@ func (am *AccountManager) Lock(address *Address) error { // If the account address is already unlocked for a duration, TimedUnlock extends or // shortens the active unlock timeout. If the address was previously unlocked // indefinitely the timeout is not altered. -func (am *AccountManager) TimedUnlock(account *Account, passphrase string, timeout int64) error { - return am.manager.TimedUnlock(account.account, passphrase, time.Duration(timeout)) +func (ks *KeyStore) TimedUnlock(account *Account, passphrase string, timeout int64) error { + return ks.keystore.TimedUnlock(account.account, passphrase, time.Duration(timeout)) } // NewAccount generates a new key and stores it into the key directory, // encrypting it with the passphrase. -func (am *AccountManager) NewAccount(passphrase string) (*Account, error) { - account, err := am.manager.NewAccount(passphrase) +func (ks *KeyStore) NewAccount(passphrase string) (*Account, error) { + account, err := ks.keystore.NewAccount(passphrase) if err != nil { return nil, err } @@ -154,13 +171,13 @@ func (am *AccountManager) NewAccount(passphrase string) (*Account, error) { } // ExportKey exports as a JSON key, encrypted with newPassphrase. -func (am *AccountManager) ExportKey(account *Account, passphrase, newPassphrase string) (key []byte, _ error) { - return am.manager.Export(account.account, passphrase, newPassphrase) +func (ks *KeyStore) ExportKey(account *Account, passphrase, newPassphrase string) (key []byte, _ error) { + return ks.keystore.Export(account.account, passphrase, newPassphrase) } // ImportKey stores the given encrypted JSON key into the key directory. -func (am *AccountManager) ImportKey(keyJSON []byte, passphrase, newPassphrase string) (account *Account, _ error) { - acc, err := am.manager.Import(keyJSON, passphrase, newPassphrase) +func (ks *KeyStore) ImportKey(keyJSON []byte, passphrase, newPassphrase string) (account *Account, _ error) { + acc, err := ks.keystore.Import(keyJSON, passphrase, newPassphrase) if err != nil { return nil, err } @@ -168,14 +185,14 @@ func (am *AccountManager) ImportKey(keyJSON []byte, passphrase, newPassphrase st } // UpdateAccount changes the passphrase of an existing account. -func (am *AccountManager) UpdateAccount(account *Account, passphrase, newPassphrase string) error { - return am.manager.Update(account.account, passphrase, newPassphrase) +func (ks *KeyStore) UpdateAccount(account *Account, passphrase, newPassphrase string) error { + return ks.keystore.Update(account.account, passphrase, newPassphrase) } // ImportPreSaleKey decrypts the given Ethereum presale wallet and stores // a key file in the key directory. The key file is encrypted with the same passphrase. -func (am *AccountManager) ImportPreSaleKey(keyJSON []byte, passphrase string) (ccount *Account, _ error) { - account, err := am.manager.ImportPreSaleKey(keyJSON, passphrase) +func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (ccount *Account, _ error) { + account, err := ks.keystore.ImportPreSaleKey(keyJSON, passphrase) if err != nil { return nil, err } diff --git a/mobile/android_test.go b/mobile/android_test.go index 3776f8291..6f5076d64 100644 --- a/mobile/android_test.go +++ b/mobile/android_test.go @@ -43,42 +43,46 @@ public class AndroidTest extends InstrumentationTestCase { public AndroidTest() {} public void testAccountManagement() { - // Create an encrypted keystore manager with light crypto parameters. - AccountManager am = new AccountManager(getInstrumentation().getContext().getFilesDir() + "/keystore", Geth.LightScryptN, Geth.LightScryptP); + // Create an encrypted keystore with light crypto parameters. + KeyStore ks = new KeyStore(getInstrumentation().getContext().getFilesDir() + "/keystore", Geth.LightScryptN, Geth.LightScryptP); try { // Create a new account with the specified encryption passphrase. - Account newAcc = am.newAccount("Creation password"); + Account newAcc = ks.newAccount("Creation password"); // Export the newly created account with a different passphrase. The returned // data from this method invocation is a JSON encoded, encrypted key-file. - byte[] jsonAcc = am.exportKey(newAcc, "Creation password", "Export password"); + byte[] jsonAcc = ks.exportKey(newAcc, "Creation password", "Export password"); // Update the passphrase on the account created above inside the local keystore. - am.updateAccount(newAcc, "Creation password", "Update password"); + ks.updateAccount(newAcc, "Creation password", "Update password"); // Delete the account updated above from the local keystore. - am.deleteAccount(newAcc, "Update password"); + ks.deleteAccount(newAcc, "Update password"); // Import back the account we've exported (and then deleted) above with yet // again a fresh passphrase. - Account impAcc = am.importKey(jsonAcc, "Export password", "Import password"); + Account impAcc = ks.importKey(jsonAcc, "Export password", "Import password"); // Create a new account to sign transactions with - Account signer = am.newAccount("Signer password"); - Hash txHash = new Hash("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"); + Account signer = ks.newAccount("Signer password"); + + Transaction tx = new Transaction( + 1, new Address("0x0000000000000000000000000000000000000000"), + new BigInt(0), new BigInt(0), new BigInt(1), null); // Random empty transaction + BigInt chain = new BigInt(1); // Chain identifier of the main net // Sign a transaction with a single authorization - byte[] signature = am.signPassphrase(signer, "Signer password", txHash.getBytes()); + Transaction signed = ks.signTxPassphrase(signer, "Signer password", tx, chain); // Sign a transaction with multiple manually cancelled authorizations - am.unlock(signer, "Signer password"); - signature = am.sign(signer.getAddress(), txHash.getBytes()); - am.lock(signer.getAddress()); + ks.unlock(signer, "Signer password"); + signed = ks.signTx(signer, tx, chain); + ks.lock(signer.getAddress()); // Sign a transaction with multiple automatically cancelled authorizations - am.timedUnlock(signer, "Signer password", 1000000000); - signature = am.sign(signer.getAddress(), txHash.getBytes()); + ks.timedUnlock(signer, "Signer password", 1000000000); + signed = ks.signTx(signer, tx, chain); } catch (Exception e) { fail(e.toString()); } diff --git a/mobile/types.go b/mobile/types.go index 9ea70ea9b..a9c8cf68c 100644 --- a/mobile/types.go +++ b/mobile/types.go @@ -132,6 +132,11 @@ type Transaction struct { tx *types.Transaction } +// NewTransaction creates a new transaction with the given properties. +func NewTransaction(nonce int64, to *Address, amount, gasLimit, gasPrice *BigInt, data []byte) *Transaction { + return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, gasLimit.bigint, gasPrice.bigint, data)} +} + func (tx *Transaction) GetData() []byte { return tx.tx.Data() } func (tx *Transaction) GetGas() int64 { return tx.tx.Gas().Int64() } func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} } |