Update for new btcd notifications.

This removes the enforced check for the spent field for tx-to-me
notifications, as this is no longer sent, and should be calculated by
wallet (not done yet).  Additionally, the full CreatedTx information
is saved with the unmined tx map, so when a tx is mined, information
about which inputs and ouputs it creates that are relevant to the
wallet can be used.
This commit is contained in:
Josh Rickmar 2013-11-04 18:58:41 -05:00
parent f809638c72
commit 85219a70d3
4 changed files with 35 additions and 35 deletions

24
cmd.go
View file

@ -355,7 +355,7 @@ func (w *BtcWallet) Track() {
w.mtx.Unlock()
replyHandlers.Lock()
replyHandlers.m[n] = w.newBlockTxHandler
replyHandlers.m[n] = w.newBlockTxOutHandler
replyHandlers.Unlock()
for _, addr := range w.GetActiveAddresses() {
w.ReqNewTxsForAddress(addr.Address)
@ -419,7 +419,7 @@ func (w *BtcWallet) RescanToBestBlock() {
replyHandlers.m[n] = func(result interface{}, e *btcjson.Error) bool {
// Rescan is compatible with new txs from connected block
// notifications, so use that handler.
_ = w.newBlockTxHandler(result, e)
_ = w.newBlockTxOutHandler(result, e)
if result != nil {
// Notify frontends of new account balance.
@ -552,9 +552,9 @@ func (w *BtcWallet) spentUtxoHandler(result interface{}, e *btcjson.Error) bool
return false
}
// newBlockTxHandler is the handler function for btcd transaction
// newBlockTxOutHandler is the handler function for btcd transaction
// notifications resulting from newly-attached blocks.
func (w *BtcWallet) newBlockTxHandler(result interface{}, e *btcjson.Error) bool {
func (w *BtcWallet) newBlockTxOutHandler(result interface{}, e *btcjson.Error) bool {
if e != nil {
log.Errorf("Tx Handler: Error %d received from btcd: %s",
e.Code, e.Message)
@ -611,34 +611,32 @@ func (w *BtcWallet) newBlockTxHandler(result interface{}, e *btcjson.Error) bool
return false
}
pkscript := btcutil.Base58Decode(pkscript58)
spent, ok := v["spent"].(bool)
if !ok {
log.Error("Tx Handler: Unspecified spent field.")
return false
spent := false
if tspent, ok := v["spent"].(bool); ok {
spent = tspent
}
// btcd sends the block and tx hashes as BE strings. Convert both
// to a LE ShaHash.
blockhash, err := btcwire.NewShaHashFromStr(blockhashBE)
if err != nil {
log.Error("Tx Handler: Block hash string cannot be parsed: " + err.Error())
log.Errorf("Tx Handler: Block hash string cannot be parsed: %v", err)
return false
}
txhash, err := btcwire.NewShaHashFromStr(txhashBE)
if err != nil {
log.Error("Tx Handler: Tx hash string cannot be parsed: " + err.Error())
log.Errorf("Tx Handler: Tx hash string cannot be parsed: %v", err)
return false
}
// TODO(jrick): btcd does not find the sender yet.
senderHash, _, _ := btcutil.DecodeAddress(sender)
receiverHash, _, err := btcutil.DecodeAddress(receiver)
if err != nil {
log.Error("Tx Handler: receiver address can not be decoded: " + err.Error())
log.Errorf("Tx Handler: receiver address can not be decoded: %v", err)
return false
}
// Add to TxStore
// Add to TxStore.
t := &tx.RecvTx{
Amt: uint64(amt),
}

View file

@ -599,7 +599,7 @@ func SendMany(reply chan []byte, msg *btcjson.Message) {
// Add hex string of raw tx to sent tx pool. If future blocks
// do not contain a tx, a resend is attempted.
UnminedTxs.Lock()
UnminedTxs.m[result.(string)] = hex.EncodeToString(createdTx.rawTx)
UnminedTxs.m[TXID(result.(string))] = createdTx
UnminedTxs.Unlock()
ReplySuccess(reply, msg.Id, result)

View file

@ -47,6 +47,19 @@ var TxFee = struct {
i: 10000, // This is a fee of 0.0001 BTC.
}
// CreatedTx is a type holding information regarding a newly-created
// transaction, including the raw bytes, inputs, and an address and UTXO
// for change (if any).
type CreatedTx struct {
rawTx []byte
inputs []*tx.Utxo
changeAddr string
changeUtxo *tx.Utxo
}
// TXID is a transaction hash identifying a transaction.
type TXID string
// UnminedTXs holds a map of transaction IDs as keys mapping to a
// hex string of a raw transaction. If sending a raw transaction
// succeeds, the tx is added to this map and checked again after each
@ -54,9 +67,9 @@ var TxFee = struct {
// this map. Otherwise, btcwallet will resend the tx to btcd.
var UnminedTxs = struct {
sync.Mutex
m map[string]string
m map[TXID]*CreatedTx
}{
m: make(map[string]string),
m: make(map[TXID]*CreatedTx),
}
// ByAmount defines the methods needed to satisify sort.Interface to
@ -118,16 +131,6 @@ func selectInputs(s tx.UtxoStore, amt uint64, minconf int) (inputs []*tx.Utxo, b
return inputs, btcout, nil
}
// createdTx is a type holding information regarding a newly-created
// transaction, including the raw bytes, inputs, and a address and UTXO
// for change.
type createdTx struct {
rawTx []byte
inputs []*tx.Utxo
changeAddr string
changeUtxo *tx.Utxo
}
// txToPairs creates a raw transaction sending the amounts for each
// address/amount pair and fee to each address and the miner. minconf
// specifies the minimum number of confirmations required before an
@ -137,7 +140,7 @@ type createdTx struct {
// address, changeUtxo will point to a unconfirmed (height = -1, zeroed
// block hash) Utxo. ErrInsufficientFunds is returned if there are not
// enough eligible unspent outputs to create the transaction.
func (w *BtcWallet) txToPairs(pairs map[string]uint64, fee uint64, minconf int) (*createdTx, error) {
func (w *BtcWallet) txToPairs(pairs map[string]uint64, fee uint64, minconf int) (*CreatedTx, error) {
// Recorded unspent transactions should not be modified until this
// finishes.
w.UtxoStore.RLock()
@ -270,5 +273,5 @@ func (w *BtcWallet) txToPairs(pairs map[string]uint64, fee uint64, minconf int)
buf := new(bytes.Buffer)
msgtx.BtcEncode(buf, btcwire.ProtocolVersion)
return &createdTx{buf.Bytes(), inputs, changeAddr, changeUtxo}, nil
return &CreatedTx{buf.Bytes(), inputs, changeAddr, changeUtxo}, nil
}

View file

@ -358,8 +358,7 @@ func NotifyNewBlockChainHeight(reply chan []byte, height int32) {
}
// NtfnBlockConnected handles btcd notifications resulting from newly
// connected blocks to the main blockchain. Currently, this only creates
// a new notification for frontends with the new blockchain height.
// connected blocks to the main blockchain.
func NtfnBlockConnected(r interface{}) {
result, ok := r.(map[string]interface{})
if !ok {
@ -382,16 +381,16 @@ func NtfnBlockConnected(r interface{}) {
return
}
height := int32(heightf)
var minedTxs []string
var minedTxs []TXID
if iminedTxs, ok := result["minedtxs"].([]interface{}); ok {
minedTxs = make([]string, len(iminedTxs))
minedTxs = make([]TXID, len(iminedTxs))
for i, iminedTx := range iminedTxs {
minedTx, ok := iminedTx.(string)
if !ok {
log.Error("blockconnected notification: mined tx is not a string")
continue
}
minedTxs[i] = minedTx
minedTxs[i] = TXID(minedTx)
}
}
@ -440,10 +439,10 @@ func NtfnBlockConnected(r interface{}) {
// transaction pool to btcd using the 'sendrawtransaction' RPC
// command.
func resendUnminedTxs() {
for _, hextx := range UnminedTxs.m {
for _, createdTx := range UnminedTxs.m {
n := <-NewJSONID
var id interface{} = fmt.Sprintf("btcwallet(%v)", n)
m, err := btcjson.CreateMessageWithId("sendrawtransaction", id, hextx)
m, err := btcjson.CreateMessageWithId("sendrawtransaction", id, string(createdTx.rawTx))
if err != nil {
log.Errorf("cannot create resend request: %v", err)
continue