diff --git a/bitcoin/sign.go b/bitcoin/sign.go index 361714b..c45e885 100644 --- a/bitcoin/sign.go +++ b/bitcoin/sign.go @@ -6,6 +6,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" "time" "github.com/btcsuite/btcd/chaincfg" @@ -80,7 +82,8 @@ func (w *BitcoinWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeL } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -149,7 +152,8 @@ func (w *BitcoinWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -278,11 +282,13 @@ func (w *BitcoinWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -310,7 +316,7 @@ func (w *BitcoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Add var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -337,7 +343,8 @@ func (w *BitcoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Add estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -359,13 +366,10 @@ func (w *BitcoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Add // Sign tx privKey, err := key.ECPrivKey() if err != nil { - return nil, fmt.Errorf("retrieving private key: %s", err.Error()) + return nil, err } pk := privKey.PubKey().SerializeCompressed() addressPub, err := btc.NewAddressPubKey(pk, w.params) - if err != nil { - return nil, fmt.Errorf("generating address pub key: %s", err.Error()) - } getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { if addressPub.EncodeAddress() == addr.EncodeAddress() { @@ -413,7 +417,7 @@ func (w *BitcoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Add } txIn.SignatureScript = script } else { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, *redeemScript, txscript.SigHashAll, privKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), *redeemScript, txscript.SigHashAll, privKey) if err != nil { return nil, err } @@ -453,7 +457,7 @@ func (w *BitcoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs if err != nil { return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -482,7 +486,7 @@ func (w *BitcoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs hashes := txscript.NewTxSigHashes(tx) for i := range tx.TxIn { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, redeemScript, txscript.SigHashAll, signingKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), redeemScript, txscript.SigHashAll, signingKey) if err != nil { continue } @@ -508,7 +512,7 @@ func (w *BitcoinWallet) multisign(ins []wi.TransactionInput, outs []wi.Transacti if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } @@ -658,7 +662,8 @@ func (w *BitcoinWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) (ui for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val, _ := strconv.ParseInt(utxo.Value, 10, 64) + inval += val break } } diff --git a/bitcoin/sign_test.go b/bitcoin/sign_test.go index bf76fac..26c2172 100644 --- a/bitcoin/sign_test.go +++ b/bitcoin/sign_test.go @@ -3,15 +3,10 @@ package bitcoin import ( "bytes" "encoding/hex" - "github.com/OpenBazaar/multiwallet/util" + "math/big" "testing" "time" - "github.com/OpenBazaar/multiwallet/cache" - "github.com/OpenBazaar/multiwallet/datastore" - "github.com/OpenBazaar/multiwallet/keys" - "github.com/OpenBazaar/multiwallet/model/mock" - "github.com/OpenBazaar/multiwallet/service" "github.com/OpenBazaar/spvwallet" "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" @@ -20,6 +15,13 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/hdkeychain" + + "github.com/OpenBazaar/multiwallet/cache" + "github.com/OpenBazaar/multiwallet/datastore" + "github.com/OpenBazaar/multiwallet/keys" + "github.com/OpenBazaar/multiwallet/model/mock" + "github.com/OpenBazaar/multiwallet/service" + "github.com/OpenBazaar/multiwallet/util" ) type FeeResponse struct { @@ -348,7 +350,8 @@ func TestBitcoinWallet_newUnsignedTransaction(t *testing.T) { } inputSource := func(target btcutil.Amount) (total btcutil.Amount, inputs []*wire.TxIn, inputValues []btcutil.Amount, scripts [][]byte, err error) { - total += btcutil.Amount(utxos[0].Value) + val, _ := new(big.Int).SetString(utxos[0].Value, 10) + total += btcutil.Amount(val.Int64()) in := wire.NewTxIn(&utxos[0].Op, []byte{}, [][]byte{}) in.Sequence = 0 // Opt-in RBF so we can bump fees inputs = append(inputs, in) @@ -390,7 +393,7 @@ func TestBitcoinWallet_CreateMultisigSignature(t *testing.T) { t.Error(err) } - sigs, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, 50) + sigs, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, *big.NewInt(50)) if err != nil { t.Error(err) } @@ -432,7 +435,7 @@ func buildTxData(w *BitcoinWallet) ([]wallet.TransactionInput, []wallet.Transact } out := wallet.TransactionOutput{ - Value: 20000, + Value: *big.NewInt(20000), Address: addr, } return []wallet.TransactionInput{in1, in2}, []wallet.TransactionOutput{out}, redeemScriptBytes, nil @@ -458,21 +461,21 @@ func TestBitcoinWallet_Multisign(t *testing.T) { t.Error(err) } - sigs1, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, 50) + sigs1, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, *big.NewInt(50)) if err != nil { t.Error(err) } if len(sigs1) != 2 { t.Error(err) } - sigs2, err := w.CreateMultisigSignature(ins, outs, key2, redeemScript, 50) + sigs2, err := w.CreateMultisigSignature(ins, outs, key2, redeemScript, *big.NewInt(50)) if err != nil { t.Error(err) } if len(sigs2) != 2 { t.Error(err) } - txBytes, err := w.Multisign(ins, outs, sigs1, sigs2, redeemScript, 50, false) + txBytes, err := w.Multisign(ins, outs, sigs1, sigs2, redeemScript, *big.NewInt(50), false) if err != nil { t.Error(err) } @@ -549,7 +552,8 @@ func TestBitcoinWallet_sweepAddress(t *testing.T) { var in wallet.TransactionInput var key *hdkeychain.ExtendedKey for _, ut := range utxos { - if ut.Value > 0 && !ut.WatchOnly { + val, _ := new(big.Int).SetString(ut.Value, 10) + if val.Int64() > 0 && !ut.WatchOnly { addr, err := w.ScriptToAddress(ut.ScriptPubkey) if err != nil { t.Error(err) @@ -564,7 +568,7 @@ func TestBitcoinWallet_sweepAddress(t *testing.T) { } in = wallet.TransactionInput{ LinkedAddress: addr, - Value: ut.Value, + Value: *val, OutpointIndex: ut.Op.Index, OutpointHash: h, } @@ -579,7 +583,8 @@ func TestBitcoinWallet_sweepAddress(t *testing.T) { // 1 of 2 P2WSH for _, ut := range utxos { - if ut.Value > 0 && ut.WatchOnly { + val, _ := new(big.Int).SetString(ut.Value, 10) + if val.Int64() > 0 && ut.WatchOnly { addr, err := w.ScriptToAddress(ut.ScriptPubkey) if err != nil { t.Error(err) @@ -590,7 +595,7 @@ func TestBitcoinWallet_sweepAddress(t *testing.T) { } in = wallet.TransactionInput{ LinkedAddress: addr, - Value: ut.Value, + Value: *val, OutpointIndex: ut.Op.Index, OutpointHash: h, } diff --git a/bitcoin/wallet.go b/bitcoin/wallet.go index faf6092..c6f1430 100644 --- a/bitcoin/wallet.go +++ b/bitcoin/wallet.go @@ -6,6 +6,8 @@ import ( "errors" "fmt" "io" + "math/big" + "strconv" "time" "github.com/OpenBazaar/multiwallet/cache" @@ -43,6 +45,13 @@ type BitcoinWallet struct { exchangeRates wi.ExchangeRates } +var ( + BitcoinCurrencyDefinition = wi.CurrencyDefinition{ + Code: "BTC", + Divisibility: 8, + } +) + func NewBitcoinWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*BitcoinWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -99,8 +108,8 @@ func (w *BitcoinWallet) CurrencyCode() string { } } -func (w *BitcoinWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *BitcoinWallet) IsDust(amount big.Int) bool { + return txrules.IsDustAmount(btc.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } func (w *BitcoinWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -171,10 +180,12 @@ func (w *BitcoinWallet) HasKey(addr btc.Address) bool { return true } -func (w *BitcoinWallet) Balance() (confirmed, unconfirmed int64) { +func (w *BitcoinWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: BitcoinCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: BitcoinCurrencyDefinition} } func (w *BitcoinWallet) Transactions() ([]wi.Txn, error) { @@ -220,11 +231,11 @@ func (w *BitcoinWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *BitcoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *BitcoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *BitcoinWallet) Spend(amount int64, addr btc.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *BitcoinWallet) Spend(amount big.Int, addr btc.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -235,7 +246,7 @@ func (w *BitcoinWallet) Spend(amount int64, addr btc.Address, feeLevel wi.FeeLev return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -252,32 +263,33 @@ func (w *BitcoinWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { return w.bumpFee(txid) } -func (w *BitcoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *BitcoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := txscript.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *BitcoinWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *BitcoinWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *BitcoinWallet) SweepAddress(ins []wi.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *BitcoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *BitcoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *BitcoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *BitcoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *BitcoinWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) { @@ -330,12 +342,12 @@ func (w *BitcoinWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } } @@ -367,6 +379,7 @@ func (w *BitcoinWallet) Broadcast(tx *wire.MsgTx) error { if err != nil { return err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -376,8 +389,8 @@ func (w *BitcoinWallet) Broadcast(tx *wire.MsgTx) error { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.Bitcoin), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.Bitcoin), } cTxn.Inputs = append(cTxn.Inputs, input) } diff --git a/bitcoincash/sign.go b/bitcoincash/sign.go index 5f182b2..48cf20a 100644 --- a/bitcoincash/sign.go +++ b/bitcoincash/sign.go @@ -5,6 +5,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" "time" "github.com/btcsuite/btcd/chaincfg" @@ -86,7 +88,8 @@ func (w *BitcoinCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi. } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -155,7 +158,8 @@ func (w *BitcoinCashWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLev } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -284,11 +288,13 @@ func (w *BitcoinCashWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -316,7 +322,7 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -343,7 +349,8 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -365,13 +372,10 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc // Sign tx privKey, err := key.ECPrivKey() if err != nil { - return nil, fmt.Errorf("retrieving private key: %s", err.Error()) + return nil, err } pk := privKey.PubKey().SerializeCompressed() addressPub, err := btc.NewAddressPubKey(pk, w.params) - if err != nil { - return nil, fmt.Errorf("generating address pub key: %s", err.Error()) - } getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { if addressPub.EncodeAddress() == addr.EncodeAddress() { @@ -412,7 +416,7 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] script, err := bchutil.SignTxOutput(w.params, tx, i, prevOutScript, txscript.SigHashAll, getKey, - getScript, txIn.SignatureScript, ins[i].Value) + getScript, txIn.SignatureScript, ins[i].Value.Int64()) if err != nil { return nil, errors.New("Failed to sign transaction") } @@ -422,7 +426,7 @@ func (w *BitcoinCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc if err != nil { return nil, err } - script, err := bchutil.RawTxInSignature(tx, i, *redeemScript, txscript.SigHashAll, priv, ins[i].Value) + script, err := bchutil.RawTxInSignature(tx, i, *redeemScript, txscript.SigHashAll, priv, ins[i].Value.Int64()) if err != nil { return nil, err } @@ -460,7 +464,7 @@ func (w *BitcoinCashWallet) createMultisigSignature(ins []wi.TransactionInput, o if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -488,7 +492,7 @@ func (w *BitcoinCashWallet) createMultisigSignature(ins []wi.TransactionInput, o } for i := range tx.TxIn { - sig, err := bchutil.RawTxInSignature(tx, i, redeemScript, txscript.SigHashAll, signingKey, ins[i].Value) + sig, err := bchutil.RawTxInSignature(tx, i, redeemScript, txscript.SigHashAll, signingKey, ins[i].Value.Int64()) if err != nil { continue } @@ -514,7 +518,7 @@ func (w *BitcoinCashWallet) multisign(ins []wi.TransactionInput, outs []wi.Trans if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -666,7 +670,8 @@ func (w *BitcoinCashWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val, _ := strconv.ParseInt(utxo.Value, 10, 64) + inval += val break } } diff --git a/bitcoincash/wallet.go b/bitcoincash/wallet.go index 96b03f8..b5df662 100644 --- a/bitcoincash/wallet.go +++ b/bitcoincash/wallet.go @@ -5,6 +5,8 @@ import ( "encoding/hex" "fmt" "io" + "math/big" + "strconv" "time" "github.com/OpenBazaar/multiwallet/cache" @@ -42,6 +44,13 @@ type BitcoinCashWallet struct { exchangeRates wi.ExchangeRates } +var ( + BitcoinCashCurrencyDefinition = wi.CurrencyDefinition{ + Code: "BCH", + Divisibility: 8, + } +) + func NewBitcoinCashWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*BitcoinCashWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -102,8 +111,8 @@ func (w *BitcoinCashWallet) CurrencyCode() string { } } -func (w *BitcoinCashWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btcutil.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *BitcoinCashWallet) IsDust(amount big.Int) bool { + return txrules.IsDustAmount(btcutil.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } func (w *BitcoinCashWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -167,10 +176,12 @@ func (w *BitcoinCashWallet) HasKey(addr btcutil.Address) bool { return true } -func (w *BitcoinCashWallet) Balance() (confirmed, unconfirmed int64) { +func (w *BitcoinCashWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: BitcoinCashCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: BitcoinCashCurrencyDefinition} } func (w *BitcoinCashWallet) Transactions() ([]wi.Txn, error) { @@ -216,11 +227,11 @@ func (w *BitcoinCashWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *BitcoinCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *BitcoinCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *BitcoinCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *BitcoinCashWallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -231,7 +242,7 @@ func (w *BitcoinCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel w return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -250,32 +261,33 @@ func (w *BitcoinCashWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error return w.bumpFee(txid) } -func (w *BitcoinCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *BitcoinCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := bchutil.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *BitcoinCashWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *BitcoinCashWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *BitcoinCashWallet) SweepAddress(ins []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *BitcoinCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *BitcoinCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *BitcoinCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *BitcoinCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *BitcoinCashWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btcutil.Address, redeemScript []byte, err error) { @@ -341,12 +353,12 @@ func (w *BitcoinCashWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } } @@ -378,6 +390,7 @@ func (w *BitcoinCashWallet) Broadcast(tx *wire.MsgTx) error { if err != nil { return err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -387,8 +400,8 @@ func (w *BitcoinCashWallet) Broadcast(tx *wire.MsgTx) error { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.BitcoinCash), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.BitcoinCash), } cTxn.Inputs = append(cTxn.Inputs, input) } diff --git a/client/transport/transport.go b/client/transport/transport.go index 5a8940d..12372d4 100644 --- a/client/transport/transport.go +++ b/client/transport/transport.go @@ -2,13 +2,14 @@ package transport import ( "errors" - tp "github.com/OpenBazaar/golang-socketio/transport" - "github.com/gorilla/websocket" - "golang.org/x/net/proxy" "io/ioutil" "net" "net/http" "time" + + tp "github.com/OpenBazaar/golang-socketio/transport" + "github.com/gorilla/websocket" + "golang.org/x/net/proxy" ) const ( diff --git a/datastore/mock.go b/datastore/mock.go index 8c66e27..303af3a 100644 --- a/datastore/mock.go +++ b/datastore/mock.go @@ -319,7 +319,7 @@ func (m *MockStxoStore) Delete(stxo wallet.Stxo) error { type txnStoreEntry struct { txn []byte - value int + value string height int timestamp time.Time watchOnly bool @@ -330,7 +330,7 @@ type MockTxnStore struct { sync.Mutex } -func (m *MockTxnStore) Put(tx []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error { +func (m *MockTxnStore) Put(tx []byte, txid, value string, height int, timestamp time.Time, watchOnly bool) error { m.Lock() defer m.Unlock() m.txns[txid] = &txnStoreEntry{ @@ -352,7 +352,7 @@ func (m *MockTxnStore) Get(txid chainhash.Hash) (wallet.Txn, error) { } return wallet.Txn{ Txid: txid.String(), - Value: int64(t.value), + Value: t.value, Height: int32(t.height), Timestamp: t.timestamp, WatchOnly: t.watchOnly, @@ -367,7 +367,7 @@ func (m *MockTxnStore) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) { for txid, t := range m.txns { txn := wallet.Txn{ Txid: txid, - Value: int64(t.value), + Value: t.value, Height: int32(t.height), Timestamp: t.timestamp, WatchOnly: t.watchOnly, diff --git a/keys/keys.go b/keys/keys.go index f902b64..c5b71d2 100644 --- a/keys/keys.go +++ b/keys/keys.go @@ -2,6 +2,7 @@ package keys import ( "errors" + "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" diff --git a/litecoin/exchange_rates.go b/litecoin/exchange_rates.go index 5d58d2c..a2ba33f 100644 --- a/litecoin/exchange_rates.go +++ b/litecoin/exchange_rates.go @@ -7,12 +7,12 @@ import ( "net/http" "reflect" "strconv" + "strings" "sync" "time" exchange "github.com/OpenBazaar/spvwallet/exchangerates" "golang.org/x/net/proxy" - "strings" ) type ExchangeRateProvider struct { @@ -103,7 +103,7 @@ func (z *LitecoinPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, er return copy, nil } -func (z *LitecoinPriceFetcher) UnitsPerCoin() int { +func (z *LitecoinPriceFetcher) UnitsPerCoin() int64 { return exchange.SatoshiPerBTC } diff --git a/litecoin/sign.go b/litecoin/sign.go index bf4af00..c8302d6 100644 --- a/litecoin/sign.go +++ b/litecoin/sign.go @@ -6,6 +6,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" "time" "github.com/btcsuite/btcd/chaincfg" @@ -82,7 +84,8 @@ func (w *LitecoinWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.Fee } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -154,7 +157,8 @@ func (w *LitecoinWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -283,11 +287,13 @@ func (w *LitecoinWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -315,7 +321,7 @@ func (w *LitecoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Ad var inputs []*wire.TxIn additionalPrevScripts := make(map[wire.OutPoint][]byte) for _, in := range ins { - val += in.Value + val += in.Value.Int64() ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -342,7 +348,8 @@ func (w *LitecoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Ad estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -364,13 +371,10 @@ func (w *LitecoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Ad // Sign tx privKey, err := key.ECPrivKey() if err != nil { - return nil, fmt.Errorf("retrieving private key: %s", err.Error()) + return nil, err } pk := privKey.PubKey().SerializeCompressed() addressPub, err := btc.NewAddressPubKey(pk, w.params) - if err != nil { - return nil, fmt.Errorf("generating address pub key: %s", err.Error()) - } getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) { if addressPub.EncodeAddress() == addr.EncodeAddress() { @@ -418,7 +422,7 @@ func (w *LitecoinWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Ad } txIn.SignatureScript = script } else { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, *redeemScript, txscript.SigHashAll, privKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), *redeemScript, txscript.SigHashAll, privKey) if err != nil { return nil, err } @@ -458,7 +462,7 @@ func (w *LitecoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs if err != nil { return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -487,7 +491,7 @@ func (w *LitecoinWallet) createMultisigSignature(ins []wi.TransactionInput, outs hashes := txscript.NewTxSigHashes(tx) for i := range tx.TxIn { - sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value, redeemScript, txscript.SigHashAll, signingKey) + sig, err := txscript.RawTxInWitnessSignature(tx, hashes, i, ins[i].Value.Int64(), redeemScript, txscript.SigHashAll, signingKey) if err != nil { continue } @@ -513,7 +517,7 @@ func (w *LitecoinWallet) multisign(ins []wi.TransactionInput, outs []wi.Transact if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -663,7 +667,8 @@ func (w *LitecoinWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) (u for _, input := range tx.TxIn { for _, utxo := range utxos { if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + val, _ := strconv.ParseInt(utxo.Value, 10, 64) + inval += val break } } diff --git a/litecoin/wallet.go b/litecoin/wallet.go index df5e297..815b734 100644 --- a/litecoin/wallet.go +++ b/litecoin/wallet.go @@ -4,18 +4,11 @@ import ( "bytes" "encoding/hex" "fmt" - "github.com/ltcsuite/ltcutil" "io" + "math/big" + "strconv" "time" - "github.com/OpenBazaar/multiwallet/cache" - "github.com/OpenBazaar/multiwallet/client" - "github.com/OpenBazaar/multiwallet/config" - "github.com/OpenBazaar/multiwallet/keys" - laddr "github.com/OpenBazaar/multiwallet/litecoin/address" - "github.com/OpenBazaar/multiwallet/model" - "github.com/OpenBazaar/multiwallet/service" - "github.com/OpenBazaar/multiwallet/util" wi "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -25,6 +18,15 @@ import ( "github.com/ltcsuite/ltcwallet/wallet/txrules" "github.com/tyler-smith/go-bip39" "golang.org/x/net/proxy" + + "github.com/OpenBazaar/multiwallet/cache" + "github.com/OpenBazaar/multiwallet/client" + "github.com/OpenBazaar/multiwallet/config" + "github.com/OpenBazaar/multiwallet/keys" + laddr "github.com/OpenBazaar/multiwallet/litecoin/address" + "github.com/OpenBazaar/multiwallet/model" + "github.com/OpenBazaar/multiwallet/service" + "github.com/OpenBazaar/multiwallet/util" ) type LitecoinWallet struct { @@ -41,6 +43,13 @@ type LitecoinWallet struct { exchangeRates wi.ExchangeRates } +var ( + LitecoinCurrencyDefinition = wi.CurrencyDefinition{ + Code: "LTC", + Divisibility: 8, + } +) + func NewLitecoinWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*LitecoinWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -100,8 +109,9 @@ func (w *LitecoinWallet) CurrencyCode() string { } } -func (w *LitecoinWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(ltcutil.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *LitecoinWallet) IsDust(amount big.Int) bool { + amt := btcutil.Amount(amount.Int64()) + return txrules.IsDustAmount(amt, 25, txrules.DefaultRelayFeePerKb) } func (w *LitecoinWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -165,10 +175,12 @@ func (w *LitecoinWallet) HasKey(addr btcutil.Address) bool { return true } -func (w *LitecoinWallet) Balance() (confirmed, unconfirmed int64) { +func (w *LitecoinWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: LitecoinCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: LitecoinCurrencyDefinition} } func (w *LitecoinWallet) Transactions() ([]wi.Txn, error) { @@ -214,11 +226,11 @@ func (w *LitecoinWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *LitecoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *LitecoinWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *LitecoinWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *LitecoinWallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -229,7 +241,7 @@ func (w *LitecoinWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.F return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -248,32 +260,33 @@ func (w *LitecoinWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { return w.bumpFee(txid) } -func (w *LitecoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *LitecoinWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := laddr.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *LitecoinWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *LitecoinWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *LitecoinWallet) SweepAddress(ins []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *LitecoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *LitecoinWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *LitecoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *LitecoinWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *LitecoinWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btcutil.Address, redeemScript []byte, err error) { @@ -339,12 +352,12 @@ func (w *LitecoinWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } fmt.Fprintln(wr, "\nKeys-----") keys, _ := w.db.Keys().GetAll() @@ -398,6 +411,7 @@ func (w *LitecoinWallet) Broadcast(tx *wire.MsgTx) error { if err != nil { return err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -407,8 +421,8 @@ func (w *LitecoinWallet) Broadcast(tx *wire.MsgTx) error { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.Litecoin), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.Litecoin), } cTxn.Inputs = append(cTxn.Inputs, input) } diff --git a/service/wallet_service.go b/service/wallet_service.go index ff8f27b..432333b 100644 --- a/service/wallet_service.go +++ b/service/wallet_service.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "math" + "math/big" "strconv" "sync" "time" @@ -352,7 +353,7 @@ func (ws *WalletService) saveSingleUtxoToDB(u model.Utxo, addrs map[string]store newU := wallet.Utxo{ Op: *wire.NewOutPoint(ch, uint32(u.Vout)), - Value: u.Satoshis, + Value: strconv.FormatInt(u.Satoshis, 10), WatchOnly: watchOnly, ScriptPubkey: scriptBytes, AtHeight: height, @@ -406,7 +407,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 msgTx := wire.NewMsgTx(int32(u.Version)) msgTx.LockTime = uint32(u.Locktime) hits := 0 - value := int64(0) + value := new(big.Int) height := int32(0) if u.Confirmations > 0 { @@ -446,12 +447,12 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 Log.Errorf("error converting outpoint hash for %s: %s", ws.coinType.String(), err.Error()) return } - v := int64(math.Round(in.Value * float64(util.SatoshisPerCoin(ws.coinType)))) + v := big.NewInt(int64(math.Round(in.Value * float64(util.SatoshisPerCoin(ws.coinType))))) cbin := wallet.TransactionInput{ OutpointHash: h, OutpointIndex: op.Index, LinkedAddress: addr, - Value: v, + Value: *v, } cb.Inputs = append(cb.Inputs, cbin) @@ -460,7 +461,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 continue } if !sa.WatchOnly { - value -= v + value.Sub(value, v) // -= v hits++ } relevant = true @@ -484,11 +485,11 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 continue } - v := int64(math.Round(out.Value * float64(util.SatoshisPerCoin(ws.coinType)))) + v := big.NewInt(int64(math.Round(out.Value * float64(util.SatoshisPerCoin(ws.coinType))))) - txout := wire.NewTxOut(v, script) + txout := wire.NewTxOut(v.Int64(), script) msgTx.TxOut = append(msgTx.TxOut, txout) - cbout := wallet.TransactionOutput{Address: addr, Value: v, Index: uint32(i)} + cbout := wallet.TransactionOutput{Address: addr, Value: *v, Index: uint32(i)} cb.Outputs = append(cb.Outputs, cbout) sa, ok := addrs[out.ScriptPubKey.Addresses[0]] @@ -496,7 +497,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 continue } if !sa.WatchOnly { - value += v + value.Add(value, v) // += v hits++ // Mark the key we received coins to as used err = ws.km.MarkKeyAsUsed(sa.Addr.ScriptAddress()) @@ -512,7 +513,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 return } - cb.Value = value + cb.Value = *value cb.WatchOnly = (hits == 0) saved, err := ws.db.Txns().Get(*txHash) if err != nil { @@ -528,7 +529,7 @@ func (ws *WalletService) saveSingleTxToDB(u model.Transaction, chainHeight int32 msgTx.BtcEncode(&buf, wire.ProtocolVersion, wire.BaseEncoding) txBytes = buf.Bytes() } - err = ws.db.Txns().Put(txBytes, txHash.String(), int(value), int(height), ts, hits == 0) + err = ws.db.Txns().Put(txBytes, txHash.String(), value.String(), int(height), ts, hits == 0) if err != nil { Log.Errorf("putting txid (%s): %s", txHash.String(), err.Error()) return diff --git a/util/balance.go b/util/balance.go index ca40b74..8202a0a 100644 --- a/util/balance.go +++ b/util/balance.go @@ -2,6 +2,8 @@ package util import ( "bytes" + "strconv" + wi "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/wire" ) @@ -13,14 +15,15 @@ func CalcBalance(utxos []wi.Utxo, txns []wi.Txn) (confirmed, unconfirmed int64) } for _, utxo := range utxos { + val, _ := strconv.ParseInt(utxo.Value, 10, 64) if !utxo.WatchOnly { if utxo.AtHeight > 0 { - confirmed += utxo.Value + confirmed += val } else { if checkIfStxoIsConfirmed(utxo.Op.Hash.String(), txmap) { - confirmed += utxo.Value + confirmed += val } else { - unconfirmed += utxo.Value + unconfirmed += val } } } diff --git a/util/coin.go b/util/coin.go index 57ec5b7..f25e45e 100644 --- a/util/coin.go +++ b/util/coin.go @@ -1,6 +1,8 @@ package util import ( + "strconv" + "github.com/OpenBazaar/wallet-interface" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -46,7 +48,8 @@ func GatherCoins(height uint32, utxos []wallet.Utxo, scriptToAddress func(script if u.AtHeight > 0 { confirmations = int32(height) - u.AtHeight } - c, err := NewCoin(u.Op.Hash, u.Op.Index, btcutil.Amount(u.Value), int64(confirmations), u.ScriptPubkey) + val, _ := strconv.ParseInt(u.Value, 10, 64) + c, err := NewCoin(u.Op.Hash, u.Op.Index, btcutil.Amount(val), int64(confirmations), u.ScriptPubkey) if err != nil { continue } diff --git a/zcash/address/address.go b/zcash/address/address.go index f9f77f4..03c7641 100644 --- a/zcash/address/address.go +++ b/zcash/address/address.go @@ -1,11 +1,11 @@ package address import ( - "errors" - "bytes" "crypto/sha256" + "errors" "fmt" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcutil" diff --git a/zcash/exchange_rates.go b/zcash/exchange_rates.go index db92ff2..ebc620e 100644 --- a/zcash/exchange_rates.go +++ b/zcash/exchange_rates.go @@ -7,12 +7,12 @@ import ( "net/http" "reflect" "strconv" + "strings" "sync" "time" exchange "github.com/OpenBazaar/spvwallet/exchangerates" "golang.org/x/net/proxy" - "strings" ) type ExchangeRateProvider struct { @@ -99,7 +99,7 @@ func (z *ZcashPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, error return z.cache, nil } -func (z *ZcashPriceFetcher) UnitsPerCoin() int { +func (z *ZcashPriceFetcher) UnitsPerCoin() int64 { return exchange.SatoshiPerBTC } diff --git a/zcash/sign.go b/zcash/sign.go index a54a162..3a386b5 100644 --- a/zcash/sign.go +++ b/zcash/sign.go @@ -6,9 +6,12 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "strconv" + "time" + "github.com/btcsuite/btcd/chaincfg" "github.com/minio/blake2b-simd" - "time" "github.com/OpenBazaar/spvwallet" wi "github.com/OpenBazaar/wallet-interface" @@ -99,7 +102,8 @@ func (w *ZCashWallet) buildTx(amount int64, addr btc.Address, feeLevel wi.FeeLev } // Get the fee per kilobyte - feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000 + f := w.GetFeePerByte(feeLevel) + feePerKB := f.Int64() * 1000 // outputs out := wire.NewTxOut(amount, script) @@ -178,7 +182,8 @@ func (w *ZCashWallet) buildSpendAllTx(addr btc.Address, feeLevel wi.FeeLevel) (* } // Get the fee - feePerByte := int64(w.GetFeePerByte(feeLevel)) + fee0 := w.GetFeePerByte(feeLevel) + feePerByte := fee0.Int64() estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH) fee := int64(estimatedSize) * feePerByte @@ -317,11 +322,13 @@ func (w *ZCashWallet) bumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { if err != nil { return nil, err } + n := new(big.Int) + n, _ = n.SetString(u.Value, 10) in := wi.TransactionInput{ LinkedAddress: addr, OutpointIndex: u.Op.Index, OutpointHash: h, - Value: int64(u.Value), + Value: *n, } transactionID, err := w.sweepAddress([]wi.TransactionInput{in}, nil, key, nil, wi.FEE_BUMP) if err != nil { @@ -350,8 +357,8 @@ func (w *ZCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Addre additionalPrevScripts := make(map[wire.OutPoint][]byte) var values []int64 for _, in := range ins { - val += in.Value - values = append(values, in.Value) + val += in.Value.Int64() + values = append(values, in.Value.Int64()) ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash)) if err != nil { return nil, err @@ -380,7 +387,8 @@ func (w *ZCashWallet) sweepAddress(ins []wi.TransactionInput, address *btc.Addre estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType) // Calculate the fee - feePerByte := int(w.GetFeePerByte(feeLevel)) + f := w.GetFeePerByte(feeLevel) + feePerByte := int(f.Int64()) fee := estimatedSize * feePerByte outVal := val - int64(fee) @@ -440,7 +448,7 @@ func (w *ZCashWallet) createMultisigSignature(ins []wi.TransactionInput, outs [] if err != nil { return sigs, err } - values = append(values, in.Value) + values = append(values, in.Value.Int64()) outpoint := wire.NewOutPoint(ch, in.OutpointIndex) input := wire.NewTxIn(outpoint, []byte{}, [][]byte{}) tx.TxIn = append(tx.TxIn, input) @@ -450,7 +458,7 @@ func (w *ZCashWallet) createMultisigSignature(ins []wi.TransactionInput, outs [] if err != nil { return sigs, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -499,7 +507,7 @@ func (w *ZCashWallet) multisign(ins []wi.TransactionInput, outs []wi.Transaction if err != nil { return nil, err } - output := wire.NewTxOut(out.Value, scriptPubkey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubkey) tx.TxOut = append(tx.TxOut, output) } @@ -613,8 +621,9 @@ func (w *ZCashWallet) estimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint } for _, input := range tx.TxIn { for _, utxo := range utxos { + val, _ := strconv.ParseInt(utxo.Value, 10, 64) if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index { - inval += utxo.Value + inval += val break } } diff --git a/zcash/sign_test.go b/zcash/sign_test.go index 43709c2..773c1b9 100644 --- a/zcash/sign_test.go +++ b/zcash/sign_test.go @@ -3,7 +3,9 @@ package zcash import ( "bytes" "encoding/hex" + "math/big" "os" + "strconv" "testing" "time" @@ -303,7 +305,8 @@ func TestZCashWallet_newUnsignedTransaction(t *testing.T) { } inputSource := func(target btcutil.Amount) (total btcutil.Amount, inputs []*wire.TxIn, inputValues []btcutil.Amount, scripts [][]byte, err error) { - total += btcutil.Amount(utxos[0].Value) + val0, _ := new(big.Int).SetString(utxos[0].Value, 10) + total += btcutil.Amount(val0.Int64()) in := wire.NewTxIn(&utxos[0].Op, []byte{}, [][]byte{}) in.Sequence = 0 // Opt-in RBF so we can bump fees inputs = append(inputs, in) @@ -345,7 +348,7 @@ func TestZCashWallet_CreateMultisigSignature(t *testing.T) { t.Error(err) } - sigs, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, 50) + sigs, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, *big.NewInt(50)) if err != nil { t.Error(err) } @@ -387,7 +390,7 @@ func buildTxData(w *ZCashWallet) ([]wallet.TransactionInput, []wallet.Transactio } out := wallet.TransactionOutput{ - Value: 20000, + Value: *big.NewInt(20000), Address: addr, } return []wallet.TransactionInput{in1, in2}, []wallet.TransactionOutput{out}, redeemScriptBytes, nil @@ -413,21 +416,21 @@ func TestZCashWallet_Multisign(t *testing.T) { t.Error(err) } - sigs1, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, 50) + sigs1, err := w.CreateMultisigSignature(ins, outs, key1, redeemScript, *big.NewInt(50)) if err != nil { t.Error(err) } if len(sigs1) != 2 { t.Error(err) } - sigs2, err := w.CreateMultisigSignature(ins, outs, key2, redeemScript, 50) + sigs2, err := w.CreateMultisigSignature(ins, outs, key2, redeemScript, *big.NewInt(50)) if err != nil { t.Error(err) } if len(sigs2) != 2 { t.Error(err) } - _, err = w.Multisign(ins, outs, sigs1, sigs2, redeemScript, 50, false) + _, err = w.Multisign(ins, outs, sigs1, sigs2, redeemScript, *big.NewInt(50), false) if err != nil { t.Error(err) } @@ -497,7 +500,8 @@ func TestZCashWallet_sweepAddress(t *testing.T) { var in wallet.TransactionInput var key *hdkeychain.ExtendedKey for _, ut := range utxos { - if ut.Value > 0 && !ut.WatchOnly { + val0, _ := strconv.ParseInt(ut.Value, 10, 64) + if val0 > 0 && !ut.WatchOnly { addr, err := w.ScriptToAddress(ut.ScriptPubkey) if err != nil { t.Error(err) @@ -512,7 +516,7 @@ func TestZCashWallet_sweepAddress(t *testing.T) { } in = wallet.TransactionInput{ LinkedAddress: addr, - Value: ut.Value, + Value: *big.NewInt(val0), OutpointIndex: ut.Op.Index, OutpointHash: h, } @@ -527,7 +531,8 @@ func TestZCashWallet_sweepAddress(t *testing.T) { // 1 of 2 P2WSH for _, ut := range utxos { - if ut.Value > 0 && ut.WatchOnly { + val0, _ := strconv.ParseInt(ut.Value, 10, 64) + if val0 > 0 && ut.WatchOnly { addr, err := w.ScriptToAddress(ut.ScriptPubkey) if err != nil { t.Error(err) @@ -538,7 +543,7 @@ func TestZCashWallet_sweepAddress(t *testing.T) { } in = wallet.TransactionInput{ LinkedAddress: addr, - Value: ut.Value, + Value: *big.NewInt(val0), OutpointIndex: ut.Op.Index, OutpointHash: h, } diff --git a/zcash/wallet.go b/zcash/wallet.go index f3fbdda..b42603e 100644 --- a/zcash/wallet.go +++ b/zcash/wallet.go @@ -4,6 +4,8 @@ import ( "encoding/hex" "fmt" "io" + "math/big" + "strconv" "time" "github.com/OpenBazaar/multiwallet/cache" @@ -39,6 +41,13 @@ type ZCashWallet struct { exchangeRates wi.ExchangeRates } +var ( + ZcashCurrencyDefinition = wi.CurrencyDefinition{ + Code: "ZCASH", + Divisibility: 8, + } +) + func NewZCashWallet(cfg config.CoinConfig, mnemonic string, params *chaincfg.Params, proxy proxy.Dialer, cache cache.Cacher, disableExchangeRates bool) (*ZCashWallet, error) { seed := bip39.NewSeed(mnemonic, "") @@ -100,8 +109,8 @@ func (w *ZCashWallet) CurrencyCode() string { } } -func (w *ZCashWallet) IsDust(amount int64) bool { - return txrules.IsDustAmount(btcutil.Amount(amount), 25, txrules.DefaultRelayFeePerKb) +func (w *ZCashWallet) IsDust(amount big.Int) bool { + return txrules.IsDustAmount(btcutil.Amount(amount.Int64()), 25, txrules.DefaultRelayFeePerKb) } func (w *ZCashWallet) MasterPrivateKey() *hd.ExtendedKey { @@ -169,10 +178,12 @@ func (w *ZCashWallet) HasKey(addr btcutil.Address) bool { return true } -func (w *ZCashWallet) Balance() (confirmed, unconfirmed int64) { +func (w *ZCashWallet) Balance() (wi.CurrencyValue, wi.CurrencyValue) { utxos, _ := w.db.Utxos().GetAll() txns, _ := w.db.Txns().GetAll(false) - return util.CalcBalance(utxos, txns) + c, u := util.CalcBalance(utxos, txns) + return wi.CurrencyValue{Value: *big.NewInt(c), Currency: ZcashCurrencyDefinition}, + wi.CurrencyValue{Value: *big.NewInt(u), Currency: ZcashCurrencyDefinition} } func (w *ZCashWallet) Transactions() ([]wi.Txn, error) { @@ -218,11 +229,11 @@ func (w *ZCashWallet) ChainTip() (uint32, chainhash.Hash) { return w.ws.ChainTip() } -func (w *ZCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) uint64 { - return w.fp.GetFeePerByte(feeLevel) +func (w *ZCashWallet) GetFeePerByte(feeLevel wi.FeeLevel) big.Int { + return *big.NewInt(int64(w.fp.GetFeePerByte(feeLevel))) } -func (w *ZCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { +func (w *ZCashWallet) Spend(amount big.Int, addr btcutil.Address, feeLevel wi.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) { var ( tx *wire.MsgTx err error @@ -233,7 +244,7 @@ func (w *ZCashWallet) Spend(amount int64, addr btcutil.Address, feeLevel wi.FeeL return nil, err } } else { - tx, err = w.buildTx(amount, addr, feeLevel, nil) + tx, err = w.buildTx(amount.Int64(), addr, feeLevel, nil) if err != nil { return nil, err } @@ -251,32 +262,33 @@ func (w *ZCashWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) { return w.bumpFee(txid) } -func (w *ZCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte uint64) uint64 { +func (w *ZCashWallet) EstimateFee(ins []wi.TransactionInput, outs []wi.TransactionOutput, feePerByte big.Int) big.Int { tx := new(wire.MsgTx) for _, out := range outs { scriptPubKey, _ := zaddr.PayToAddrScript(out.Address) - output := wire.NewTxOut(out.Value, scriptPubKey) + output := wire.NewTxOut(out.Value.Int64(), scriptPubKey) tx.TxOut = append(tx.TxOut, output) } estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH) - fee := estimatedSize * int(feePerByte) - return uint64(fee) + fee := estimatedSize * int(feePerByte.Int64()) + return *big.NewInt(int64(fee)) } -func (w *ZCashWallet) EstimateSpendFee(amount int64, feeLevel wi.FeeLevel) (uint64, error) { - return w.estimateSpendFee(amount, feeLevel) +func (w *ZCashWallet) EstimateSpendFee(amount big.Int, feeLevel wi.FeeLevel) (big.Int, error) { + val, err := w.estimateSpendFee(amount.Int64(), feeLevel) + return *big.NewInt(int64(val)), err } func (w *ZCashWallet) SweepAddress(ins []wi.TransactionInput, address *btcutil.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wi.FeeLevel) (*chainhash.Hash, error) { return w.sweepAddress(ins, address, key, redeemScript, feeLevel) } -func (w *ZCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wi.Signature, error) { - return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte) +func (w *ZCashWallet) CreateMultisigSignature(ins []wi.TransactionInput, outs []wi.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte big.Int) ([]wi.Signature, error) { + return w.createMultisigSignature(ins, outs, key, redeemScript, feePerByte.Uint64()) } -func (w *ZCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) { - return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte, broadcast) +func (w *ZCashWallet) Multisign(ins []wi.TransactionInput, outs []wi.TransactionOutput, sigs1 []wi.Signature, sigs2 []wi.Signature, redeemScript []byte, feePerByte big.Int, broadcast bool) ([]byte, error) { + return w.multisign(ins, outs, sigs1, sigs2, redeemScript, feePerByte.Uint64(), broadcast) } func (w *ZCashWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btcutil.Address, redeemScript []byte, err error) { @@ -342,12 +354,12 @@ func (w *ZCashWallet) DumpTables(wr io.Writer) { fmt.Fprintln(wr, "Transactions-----") txns, _ := w.db.Txns().GetAll(true) for _, tx := range txns { - fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %d, WatchOnly: %t\n", tx.Txid, int(tx.Height), int(tx.Value), tx.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Height: %d, Value: %s, WatchOnly: %t\n", tx.Txid, int(tx.Height), tx.Value, tx.WatchOnly) } fmt.Fprintln(wr, "\nUtxos-----") utxos, _ := w.db.Utxos().GetAll() for _, u := range utxos { - fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %d, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), int(u.Value), u.WatchOnly) + fmt.Fprintf(wr, "Hash: %s, Index: %d, Height: %d, Value: %s, WatchOnly: %t\n", u.Op.Hash.String(), int(u.Op.Index), int(u.AtHeight), u.Value, u.WatchOnly) } } @@ -381,6 +393,7 @@ func (w *ZCashWallet) Broadcast(tx *wire.MsgTx) (string, error) { if err != nil { return "", err } + val, _ := strconv.ParseInt(u.Value, 10, 64) input := model.Input{ Txid: in.PreviousOutPoint.Hash.String(), Vout: int(in.PreviousOutPoint.Index), @@ -390,8 +403,8 @@ func (w *ZCashWallet) Broadcast(tx *wire.MsgTx) (string, error) { Sequence: uint32(in.Sequence), N: n, Addr: addr.String(), - Satoshis: u.Value, - Value: float64(u.Value) / util.SatoshisPerCoin(wi.Zcash), + Satoshis: val, + Value: float64(val) / util.SatoshisPerCoin(wi.Zcash), } cTxn.Inputs = append(cTxn.Inputs, input) }