From fb340fc4fe8902a40450f7420cc06399f36ce8f5 Mon Sep 17 00:00:00 2001 From: Chris Pacia Date: Fri, 1 Jun 2018 16:54:10 -0400 Subject: [PATCH 1/6] Ethereum modifications --- wallet.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/wallet.go b/wallet.go index 7b2fa40..52148c8 100644 --- a/wallet.go +++ b/wallet.go @@ -38,12 +38,6 @@ type Wallet interface { // Parse the address string and return an address interface DecodeAddress(addr string) (btc.Address, error) - // Turn the given output script into an address - ScriptToAddress(script []byte) (btc.Address, error) - - // Turn the given address into an output script - AddressToScript(addr btc.Address) ([]byte, error) - // Returns if the wallet has the key for the given address HasKey(addr btc.Address) bool @@ -87,7 +81,7 @@ type Wallet interface { GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) // Add a script to the wallet and get notifications back when coins are received or spent from it - AddWatchedScript(script []byte) error + AddWatchedAddress(address btc.Address) error // Add a callback for incoming transactions AddTransactionListener(func(TransactionCallback)) @@ -136,7 +130,7 @@ type TransactionCallback struct { } type TransactionOutput struct { - ScriptPubKey []byte + Address btc.Address Value int64 Index uint32 } @@ -144,7 +138,7 @@ type TransactionOutput struct { type TransactionInput struct { OutpointHash []byte OutpointIndex uint32 - LinkedScriptPubKey []byte + Address btc.Address Value int64 } @@ -156,7 +150,7 @@ type TransactionRecord struct { Txid string Index uint32 Value int64 - ScriptPubKey string + Address string Spent bool Timestamp time.Time } From 3ded693a4a4df340b1f5ea8348eb35a4d74aa5de Mon Sep 17 00:00:00 2001 From: Ashwin Mangale Date: Thu, 7 Jun 2018 15:43:55 +0530 Subject: [PATCH 2/6] make CurrentAddress agnostic --- wallet.go | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/wallet.go b/wallet.go index 52148c8..adf2eb9 100644 --- a/wallet.go +++ b/wallet.go @@ -2,20 +2,36 @@ package wallet import ( "errors" - "github.com/btcsuite/btcd/chaincfg" + "time" + "github.com/btcsuite/btcd/chaincfg/chainhash" btc "github.com/btcsuite/btcutil" hd "github.com/btcsuite/btcutil/hdkeychain" - "time" ) +// WalletAddress is a coin agnostic subset +// of the btc.Address interface. +// The only method not included is +// IsForNet(*chaincfg.Params) bool +// which is coin agnostic +type WalletAddress interface { + String() string + EncodeAddress() string + ScriptAddress() []byte +} + +// Wallet is the interface that each coin usable +// on OpenBazaar must implement type Wallet interface { // Start the wallet Start() // Return the network parameters - Params() *chaincfg.Params + // This method is not required as a part of the interface + // because params is embedded inside the BTC coin family + // wallet implementation + // Params() *chaincfg.Params // Returns the type of crytocurrency this wallet implements CurrencyCode() string @@ -30,7 +46,7 @@ type Wallet interface { MasterPublicKey() *hd.ExtendedKey // Get the current address for the given purpose - CurrentAddress(purpose KeyPurpose) btc.Address + CurrentAddress(purpose KeyPurpose) WalletAddress // Returns a fresh address that has never been returned by this function NewAddress(purpose KeyPurpose) btc.Address @@ -130,16 +146,16 @@ type TransactionCallback struct { } type TransactionOutput struct { - Address btc.Address - Value int64 - Index uint32 + Address btc.Address + Value int64 + Index uint32 } type TransactionInput struct { - OutpointHash []byte - OutpointIndex uint32 - Address btc.Address - Value int64 + OutpointHash []byte + OutpointIndex uint32 + Address btc.Address + Value int64 } // OpenBazaar uses p2sh addresses for escrow. This object can be used to store a record of a @@ -147,12 +163,12 @@ type TransactionInput struct { // value and be market as spent when the UXTO is spent. Outgoing transactions should have a // negative value. The spent field isn't relevant for outgoing transactions. type TransactionRecord struct { - Txid string - Index uint32 - Value int64 - Address string - Spent bool - Timestamp time.Time + Txid string + Index uint32 + Value int64 + Address string + Spent bool + Timestamp time.Time } // This object contains a single signature for a multisig transaction. InputIndex specifies From aadbfbb5f12372d2e76abfb06044fb5f0429a561 Mon Sep 17 00:00:00 2001 From: Ashwin Mangale Date: Thu, 7 Jun 2018 18:13:25 +0530 Subject: [PATCH 3/6] remove btcutil address --- wallet.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/wallet.go b/wallet.go index adf2eb9..12a215f 100644 --- a/wallet.go +++ b/wallet.go @@ -49,13 +49,13 @@ type Wallet interface { CurrentAddress(purpose KeyPurpose) WalletAddress // Returns a fresh address that has never been returned by this function - NewAddress(purpose KeyPurpose) btc.Address + NewAddress(purpose KeyPurpose) WalletAddress // Parse the address string and return an address interface - DecodeAddress(addr string) (btc.Address, error) + DecodeAddress(addr string) (WalletAddress, error) // Returns if the wallet has the key for the given address - HasKey(addr btc.Address) bool + HasKey(addr WalletAddress) bool // Get the confirmed and unconfirmed balances Balance() (confirmed, unconfirmed int64) @@ -73,7 +73,7 @@ type Wallet interface { GetFeePerByte(feeLevel FeeLevel) uint64 // Send bitcoins to an external wallet - Spend(amount int64, addr btc.Address, feeLevel FeeLevel) (*chainhash.Hash, error) + Spend(amount int64, addr WalletAddress, feeLevel FeeLevel) (*chainhash.Hash, error) // Bump the fee for the given transaction BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) @@ -85,7 +85,7 @@ type Wallet interface { EstimateSpendFee(amount int64, feeLevel FeeLevel) (uint64, error) // Build and broadcast a transaction that sweeps all coins from an address. If it is a p2sh multisig, the redeemScript must be included - SweepAddress(utxos []Utxo, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel FeeLevel) (*chainhash.Hash, error) + SweepAddress(utxos []Utxo, address *WalletAddress, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel FeeLevel) (*chainhash.Hash, error) // Create a signature for a multisig transaction CreateMultisigSignature(ins []TransactionInput, outs []TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]Signature, error) @@ -97,7 +97,7 @@ type Wallet interface { GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) // Add a script to the wallet and get notifications back when coins are received or spent from it - AddWatchedAddress(address btc.Address) error + AddWatchedAddress(address WalletAddress) error // Add a callback for incoming transactions AddTransactionListener(func(TransactionCallback)) @@ -146,16 +146,18 @@ type TransactionCallback struct { } type TransactionOutput struct { - Address btc.Address - Value int64 - Index uint32 + Address WalletAddress + ScriptPubKey []byte + Value int64 + Index uint32 } type TransactionInput struct { - OutpointHash []byte - OutpointIndex uint32 - Address btc.Address - Value int64 + OutpointHash []byte + OutpointIndex uint32 + Address WalletAddress + LinkedScriptPubKey []byte + Value int64 } // OpenBazaar uses p2sh addresses for escrow. This object can be used to store a record of a From 892f7652990cf07e1df6d3dfddaeaa5f6f8678ab Mon Sep 17 00:00:00 2001 From: Ashwin Mangale Date: Mon, 2 Jul 2018 23:49:26 +0530 Subject: [PATCH 4/6] add ethereum cointype --- datastore.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/datastore.go b/datastore.go index 499e3f2..ef0a636 100644 --- a/datastore.go +++ b/datastore.go @@ -2,10 +2,11 @@ package wallet import ( "bytes" + "time" + "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "time" ) type CoinType uint32 @@ -15,6 +16,7 @@ const ( Litecoin = 1 Zcash = 133 BitcoinCash CoinType = 145 + Ethereum CoinType = 88 ) func (c *CoinType) String() string { @@ -27,6 +29,8 @@ func (c *CoinType) String() string { return "Zcash" case Litecoin: return "Litecoin" + case Ethereum: + return "Ethereum" default: return "" } From f17f7ebfd68cf34244c1298a0a68e756d09f9c5a Mon Sep 17 00:00:00 2001 From: Ashwin Mangale Date: Wed, 1 Aug 2018 23:07:24 +0530 Subject: [PATCH 5/6] merge refactor changes --- datastore.go | 26 ++++++++++++++++++++++++-- exchange_rates.go | 0 wallet.go | 16 +++++++++------- 3 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 exchange_rates.go diff --git a/datastore.go b/datastore.go index ef0a636..23fb23a 100644 --- a/datastore.go +++ b/datastore.go @@ -9,14 +9,19 @@ import ( "github.com/btcsuite/btcd/wire" ) +type Coin interface { + String() string + CurrencyCode() string +} + type CoinType uint32 const ( Bitcoin CoinType = 0 Litecoin = 1 Zcash = 133 - BitcoinCash CoinType = 145 - Ethereum CoinType = 88 + BitcoinCash = 145 + Ethereum = 60 ) func (c *CoinType) String() string { @@ -36,6 +41,23 @@ func (c *CoinType) String() string { } } +func (c *CoinType) CurrencyCode() string { + switch *c { + case Bitcoin: + return "BTC" + case BitcoinCash: + return "BCH" + case Zcash: + return "ZEC" + case Litecoin: + return "LTC" + case Ethereum: + return "ETH" + default: + return "" + } +} + type Datastore interface { Utxos() Utxos Stxos() Stxos diff --git a/exchange_rates.go b/exchange_rates.go new file mode 100644 index 0000000..e69de29 diff --git a/wallet.go b/wallet.go index 12a215f..edfa69c 100644 --- a/wallet.go +++ b/wallet.go @@ -45,6 +45,10 @@ type Wallet interface { // Get the master public key MasterPublicKey() *hd.ExtendedKey + // Generate a child key using the given chaincode. The key is used in multisig transactions. + // For most implementations this should just be child key 0. + ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) + // Get the current address for the given purpose CurrentAddress(purpose KeyPurpose) WalletAddress @@ -85,9 +89,9 @@ type Wallet interface { EstimateSpendFee(amount int64, feeLevel FeeLevel) (uint64, error) // Build and broadcast a transaction that sweeps all coins from an address. If it is a p2sh multisig, the redeemScript must be included - SweepAddress(utxos []Utxo, address *WalletAddress, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel FeeLevel) (*chainhash.Hash, error) + SweepAddress(ins []TransactionInput, address *WalletAddress, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel FeeLevel) (*chainhash.Hash, error) - // Create a signature for a multisig transaction + // Create a signature for a multisig transaction. CreateMultisigSignature(ins []TransactionInput, outs []TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]Signature, error) // Combine signatures and optionally broadcast @@ -96,7 +100,7 @@ type Wallet interface { // Generate a multisig script from public keys. If a timeout is included the returned script should be a timelocked escrow which releases using the timeoutKey. GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) - // Add a script to the wallet and get notifications back when coins are received or spent from it + // Add an address to the wallet and get notifications back when coins are received or spent from it AddWatchedAddress(address WalletAddress) error // Add a callback for incoming transactions @@ -135,7 +139,7 @@ const ( // This callback is passed to any registered transaction listeners when a transaction is detected // for the wallet. type TransactionCallback struct { - Txid []byte + Txid string Outputs []TransactionOutput Inputs []TransactionInput Height int32 @@ -147,7 +151,6 @@ type TransactionCallback struct { type TransactionOutput struct { Address WalletAddress - ScriptPubKey []byte Value int64 Index uint32 } @@ -155,8 +158,7 @@ type TransactionOutput struct { type TransactionInput struct { OutpointHash []byte OutpointIndex uint32 - Address WalletAddress - LinkedScriptPubKey []byte + LinkedAddress WalletAddress Value int64 } From f315aeb1252e3873672c462c50737563479df888 Mon Sep 17 00:00:00 2001 From: Ashwin Mangale Date: Wed, 1 Aug 2018 23:11:16 +0530 Subject: [PATCH 6/6] merge refactor changes --- exchange_rates.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/exchange_rates.go b/exchange_rates.go index e69de29..20a0295 100644 --- a/exchange_rates.go +++ b/exchange_rates.go @@ -0,0 +1,19 @@ +package wallet + +type ExchangeRates interface { + + /* Fetch the exchange rate for the given currency + It is OK if this returns from a cache. */ + GetExchangeRate(currencyCode string) (float64, error) + + // Update the prices with the current exchange rate before returning + GetLatestRate(currencyCode string) (float64, error) + + // Returns all available rates + GetAllRates(cacheOK bool) (map[string]float64, error) + + /* Return the number of currency units per coin. For example, in bitcoin + this is 100m satoshi per BTC. This is used when converting from fiat + to the smaller currency unit. */ + UnitsPerCoin() int +}