aboutsummaryrefslogtreecommitdiffstats
path: root/accounts/accounts.go
blob: 9592110e3b0463b1592db0001786dc347e0c4b8f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

// Package accounts implements high level Ethereum account management.
package accounts

import (
    "math/big"

    ethereum "github.com/tangerine-network/go-tangerine"
    "github.com/tangerine-network/go-tangerine/common"
    "github.com/tangerine-network/go-tangerine/core/types"
    "github.com/tangerine-network/go-tangerine/event"
)

// Account represents an Ethereum account located at a specific location defined
// by the optional URL field.
type Account struct {
    Address common.Address `json:"address"` // Ethereum account address derived from the key
    URL     URL            `json:"url"`     // Optional resource locator within a backend
}

// Wallet represents a software or hardware wallet that might contain one or more
// accounts (derived from the same seed).
type Wallet interface {
    // URL retrieves the canonical path under which this wallet is reachable. It is
    // user by upper layers to define a sorting order over all wallets from multiple
    // backends.
    URL() URL

    // Status returns a textual status to aid the user in the current state of the
    // wallet. It also returns an error indicating any failure the wallet might have
    // encountered.
    Status() (string, error)

    // Open initializes access to a wallet instance. It is not meant to unlock or
    // decrypt account keys, rather simply to establish a connection to hardware
    // wallets and/or to access derivation seeds.
    //
    // The passphrase parameter may or may not be used by the implementation of a
    // particular wallet instance. The reason there is no passwordless open method
    // is to strive towards a uniform wallet handling, oblivious to the different
    // backend providers.
    //
    // Please note, if you open a wallet, you must close it to release any allocated
    // resources (especially important when working with hardware wallets).
    Open(passphrase string) error

    // Close releases any resources held by an open wallet instance.
    Close() error

    // Accounts retrieves the list of signing accounts the wallet is currently aware
    // of. For hierarchical deterministic wallets, the list will not be exhaustive,
    // rather only contain the accounts explicitly pinned during account derivation.
    Accounts() []Account

    // Contains returns whether an account is part of this particular wallet or not.
    Contains(account Account) bool

    // Derive attempts to explicitly derive a hierarchical deterministic account at
    // the specified derivation path. If requested, the derived account will be added
    // to the wallet's tracked account list.
    Derive(path DerivationPath, pin bool) (Account, error)

    // SelfDerive sets a base account derivation path from which the wallet attempts
    // to discover non zero accounts and automatically add them to list of tracked
    // accounts.
    //
    // Note, self derivaton will increment the last component of the specified path
    // opposed to decending into a child path to allow discovering accounts starting
    // from non zero components.
    //
    // You can disable automatic account discovery by calling SelfDerive with a nil
    // chain state reader.
    SelfDerive(base DerivationPath, chain ethereum.ChainStateReader)

    // SignHash requests the wallet to sign the given hash.
    //
    // It looks up the account specified either solely via its address contained within,
    // or optionally with the aid of any location metadata from the embedded URL field.
    //
    // If the wallet requires additional authentication to sign the request (e.g.
    // a password to decrypt the account, or a PIN code o verify the transaction),
    // an AuthNeededError instance will be returned, containing infos for the user
    // about which fields or actions are needed. The user may retry by providing
    // the needed details via SignHashWithPassphrase, or by other means (e.g. unlock
    // the account in a keystore).
    SignHash(account Account, hash []byte) ([]byte, error)

    // SignTx requests the wallet to sign the given transaction.
    //
    // It looks up the account specified either solely via its address contained within,
    // or optionally with the aid of any location metadata from the embedded URL field.
    //
    // If the wallet requires additional authentication to sign the request (e.g.
    // a password to decrypt the account, or a PIN code to verify the transaction),
    // an AuthNeededError instance will be returned, containing infos for the user
    // about which fields or actions are needed. The user may retry by providing
    // the needed details via SignTxWithPassphrase, or by other means (e.g. unlock
    // the account in a keystore).
    SignTx(account Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error)

    // SignHashWithPassphrase requests the wallet to sign the given hash with the
    // given passphrase as extra authentication information.
    //
    // It looks up the account specified either solely via its address contained within,
    // or optionally with the aid of any location metadata from the embedded URL field.
    SignHashWithPassphrase(account Account, passphrase string, hash []byte) ([]byte, error)

    // SignTxWithPassphrase requests the wallet to sign the given transaction, with the
    // given passphrase as extra authentication information.
    //
    // It looks up the account specified either solely via its address contained within,
    // or optionally with the aid of any location metadata from the embedded URL field.
    SignTxWithPassphrase(account Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error)
}

// Backend is a "wallet provider" that may contain a batch of accounts they can
// sign transactions with and upon request, do so.
type Backend interface {
    // Wallets retrieves the list of wallets the backend is currently aware of.
    //
    // The returned wallets are not opened by default. For software HD wallets this
    // means that no base seeds are decrypted, and for hardware wallets that no actual
    // connection is established.
    //
    // The resulting wallet list will be sorted alphabetically based on its internal
    // URL assigned by the backend. Since wallets (especially hardware) may come and
    // go, the same wallet might appear at a different positions in the list during
    // subsequent retrievals.
    Wallets() []Wallet

    // Subscribe creates an async subscription to receive notifications when the
    // backend detects the arrival or departure of a wallet.
    Subscribe(sink chan<- WalletEvent) event.Subscription
}

// WalletEventType represents the different event types that can be fired by
// the wallet subscription subsystem.
type WalletEventType int

const (
    // WalletArrived is fired when a new wallet is detected either via USB or via
    // a filesystem event in the keystore.
    WalletArrived WalletEventType = iota

    // WalletOpened is fired when a wallet is successfully opened with the purpose
    // of starting any background processes such as automatic key derivation.
    WalletOpened

    // WalletDropped
    WalletDropped
)

// WalletEvent is an event fired by an account backend when a wallet arrival or
// departure is detected.
type WalletEvent struct {
    Wallet Wallet          // Wallet instance arrived or departed
    Kind   WalletEventType // Event type that happened in the system
}