Skip to content

Commit

Permalink
Add coinbase flag (boolean) to UTXO response trezor#236
Browse files Browse the repository at this point in the history
  • Loading branch information
martinboehm committed Jul 23, 2019
1 parent 45f5d11 commit 39f2c73
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 12 deletions.
1 change: 1 addition & 0 deletions api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ type Utxo struct {
Address string `json:"address,omitempty"`
Path string `json:"path,omitempty"`
Locktime uint32 `json:"lockTime,omitempty"`
Coinbase bool `json:"coinbase,omitempty"`
}

// Utxos is array of Utxo
Expand Down
20 changes: 19 additions & 1 deletion api/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,11 +843,16 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
// report only outpoints that are not spent in mempool
_, e := spentInMempool[bchainTx.Txid+strconv.Itoa(i)]
if !e {
coinbase := false
if len(bchainTx.Vin) == 1 && len(bchainTx.Vin[0].Coinbase) > 0 {
coinbase = true
}
r = append(r, Utxo{
Txid: bchainTx.Txid,
Vout: int32(i),
AmountSat: (*Amount)(&vout.ValueSat),
Locktime: bchainTx.LockTime,
Coinbase: coinbase,
})
}
}
Expand Down Expand Up @@ -882,12 +887,25 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
}
_, e := spentInMempool[txid+strconv.Itoa(int(utxo.Vout))]
if !e {
confirmations := bestheight - int(utxo.Height) + 1
coinbase := false
// for performance reasons, check coinbase transactions only in minimim confirmantion range
if confirmations < w.chainParser.MinimumCoinbaseConfirmations() {
ta, err := w.db.GetTxAddresses(txid)
if err != nil {
return nil, err
}
if len(ta.Inputs) == 1 && len(ta.Inputs[0].AddrDesc) == 0 && IsZeroBigInt(&ta.Inputs[0].ValueSat) {
coinbase = true
}
}
r = append(r, Utxo{
Txid: txid,
Vout: utxo.Vout,
AmountSat: (*Amount)(&utxo.ValueSat),
Height: int(utxo.Height),
Confirmations: bestheight - int(utxo.Height) + 1,
Confirmations: confirmations,
Coinbase: coinbase,
})
}
checksum.Sub(&checksum, &utxo.ValueSat)
Expand Down
5 changes: 5 additions & 0 deletions bchain/baseparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ func (p *BaseParser) GetChainType() ChainType {
return ChainBitcoinType
}

// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
func (p *BaseParser) MinimumCoinbaseConfirmations() int {
return 0
}

// PackTx packs transaction to byte array using protobuf
func (p *BaseParser) PackTx(tx *Tx, height uint32, blockTime int64) ([]byte, error) {
var err error
Expand Down
29 changes: 18 additions & 11 deletions bchain/coins/btc/bitcoinparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
// BitcoinParser handle
type BitcoinParser struct {
*bchain.BaseParser
Params *chaincfg.Params
OutputScriptToAddressesFunc OutputScriptToAddressesFunc
XPubMagic uint32
XPubMagicSegwitP2sh uint32
XPubMagicSegwitNative uint32
Slip44 uint32
Params *chaincfg.Params
OutputScriptToAddressesFunc OutputScriptToAddressesFunc
XPubMagic uint32
XPubMagicSegwitP2sh uint32
XPubMagicSegwitNative uint32
Slip44 uint32
minimumCoinbaseConfirmations int
}

// NewBitcoinParser returns new BitcoinParser instance
Expand All @@ -39,11 +40,12 @@ func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser
BlockAddressesToKeep: c.BlockAddressesToKeep,
AmountDecimalPoint: 8,
},
Params: params,
XPubMagic: c.XPubMagic,
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
Slip44: c.Slip44,
Params: params,
XPubMagic: c.XPubMagic,
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
Slip44: c.Slip44,
minimumCoinbaseConfirmations: c.MinimumCoinbaseConfirmations,
}
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
return p
Expand Down Expand Up @@ -326,6 +328,11 @@ func (p *BitcoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
return tx, height, nil
}

// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
func (p *BitcoinParser) MinimumCoinbaseConfirmations() int {
return p.minimumCoinbaseConfirmations
}

func (p *BitcoinParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchain.AddressDescriptor, error) {
var a btcutil.Address
var err error
Expand Down
5 changes: 5 additions & 0 deletions bchain/coins/btc/bitcoinrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type Configuration struct {
Slip44 uint32 `json:"slip44,omitempty"`
AlternativeEstimateFee string `json:"alternativeEstimateFee,omitempty"`
AlternativeEstimateFeeParams string `json:"alternativeEstimateFeeParams,omitempty"`
MinimumCoinbaseConfirmations int `json:"minimumCoinbaseConfirmations,omitempty"`
}

// NewBitcoinRPC returns new BitcoinRPC instance.
Expand All @@ -71,6 +72,10 @@ func NewBitcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationT
if c.BlockAddressesToKeep < 100 {
c.BlockAddressesToKeep = 100
}
// default MinimumCoinbaseConfirmations is 100
if c.MinimumCoinbaseConfirmations == 0 {
c.MinimumCoinbaseConfirmations = 100
}
// at least 1 mempool worker/subworker for synchronous mempool synchronization
if c.MempoolWorkers < 1 {
c.MempoolWorkers = 1
Expand Down
2 changes: 2 additions & 0 deletions bchain/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ type BlockChainParser interface {
KeepBlockAddresses() int
// AmountDecimals returns number of decimal places in coin amounts
AmountDecimals() int
// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
MinimumCoinbaseConfirmations() int
// AmountToDecimalString converts amount in big.Int to string with decimal point in the correct place
AmountToDecimalString(a *big.Int) string
// AmountToBigInt converts amount in json.Number (string) to big.Int
Expand Down
10 changes: 10 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ Returns array of unspent transaction outputs of address or xpub, applicable only

Unconfirmed utxos do not have field *height*, the field *confirmations* has value *0* and may contain field *lockTime*, if not zero.

Coinbase utxos do have field *coinbase* set to true, however due to performance reasons only up to minimum coinbase confirmations limit (100). After this limit, utxos are not detected as coinbase.

```
GET /api/v2/utxo/<address|xpub>[?confirmed=true]
```
Expand All @@ -422,6 +424,14 @@ Response:
"confirmations": 0,
"lockTime": 2648100
},
{
"txid": "a79e396a32e10856c97b95f43da7e9d2b9a11d446f7638dbd75e5e7603128cac",
"vout": 1,
"value": "39748685",
"height": 2648043,
"confirmations": 47,
"coinbase": true
},
{
"txid": "de4f379fdc3ea9be063e60340461a014f372a018d70c3db35701654e7066b3ef",
"vout": 0,
Expand Down

0 comments on commit 39f2c73

Please sign in to comment.