Link spending transaction to output in explorer

pull/56/head
Martin Boehm 2018-09-03 17:25:57 +02:00
parent 984f24a76d
commit 63ad3ffff2
2 changed files with 58 additions and 26 deletions

View File

@ -45,6 +45,7 @@ func (w *Worker) getAddressesFromVout(vout *bchain.Vout) (bchain.AddressDescript
// GetTransaction reads transaction data from txid
func (w *Worker) GetTransaction(txid string, bestheight uint32, spendingTxs bool) (*Tx, error) {
start := time.Now()
bchainTx, height, err := w.txCache.GetTransaction(txid, bestheight)
if err != nil {
return nil, NewApiError(fmt.Sprintf("Tx not found, %v", err), true)
@ -123,7 +124,39 @@ func (w *Worker) GetTransaction(txid string, bestheight uint32, spendingTxs bool
if ta != nil {
vout.Spent = ta.Outputs[i].Spent
if spendingTxs && vout.Spent {
// TODO
// find transaction that spent this output
// there is not an index, it must be found in addresses -> txaddresses -> tx
// given that each step is more and more selective, it is not
err = w.db.GetAddrDescTransactions(vout.ScriptPubKey.AddrDesc, height, ^uint32(0), func(t string, index uint32, isOutput bool) error {
if isOutput == false {
tsp, err := w.db.GetTxAddresses(t)
if err != nil {
glog.Warning("DB inconsistency: tx ", t, ": not found in txAddresses")
} else {
if len(tsp.Inputs) > int(index) {
if tsp.Inputs[index].ValueSat.Cmp(&vout.ValueSat) == 0 {
spentTx, spentHeight, err := w.txCache.GetTransaction(t, bestheight)
if err != nil {
glog.Warning("Tx ", t, ": not found")
} else {
if len(spentTx.Vin) > int(index) {
if spentTx.Vin[index].Txid == bchainTx.Txid {
vout.SpentTxID = t
vout.SpentHeight = int(spentHeight)
vout.SpentIndex = int(index)
return &db.StopIteration{}
}
}
}
}
}
}
}
return nil
})
if err != nil {
glog.Errorf("GetAddrDescTransactions error %v, %v, output %v", err, vout.ScriptPubKey.AddrDesc)
}
}
}
}
@ -150,6 +183,7 @@ func (w *Worker) GetTransaction(txid string, bestheight uint32, spendingTxs bool
Vin: vins,
Vout: vouts,
}
glog.Info("GetTransaction ", txid, " finished in ", time.Since(start))
return r, nil
}
@ -238,6 +272,7 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn
if err != nil {
glog.Errorf("tai.Addresses error %v, tx %v, output %v, tao %+v", err, txid, i, tao)
}
vout.Spent = tao.Spent
}
// for coinbase transactions valIn is 0
feesSat.Sub(&valInSat, &valOutSat)
@ -374,6 +409,6 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, onlyTxids b
TotalPages: totalPages,
TxsOnPage: txsOnPage,
}
glog.Info(address, " finished in ", time.Since(start))
glog.Info("GetAddress ", address, " finished in ", time.Since(start))
return r, nil
}

View File

@ -4,30 +4,30 @@
<div class="col-xs-7 col-md-8 ellipsis">
<a href="/explorer/tx/{{$tx.Txid}}">{{$tx.Txid}}</a>
</div>
{{if $tx.Confirmations}}
{{- if $tx.Confirmations -}}
<div class="col-xs-5 col-md-4 text-muted text-right">mined {{formatUnixTime $tx.Blocktime}}</div>
{{end}}
{{- end -}}
</div>
<div class="row line-mid">
<div class="col-md-5">
<div class="row">
<table class="table data-table">
<tbody>
{{range $vin := $tx.Vin}}
{{- range $vin := $tx.Vin -}}
<tr>
<td>
{{range $a := $vin.Addresses}}
{{- range $a := $vin.Addresses}}
<span class="ellipsis float-left">
{{if and (ne $a $addr) $vin.Searchable}}<a href="/explorer/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
</span>
{{else}}
{{- else -}}
<span class="float-left">No Inputs (Newly Generated Coins)</span>
{{end}}{{if $vin.Addresses}}
{{- end -}}{{- if $vin.Addresses -}}
<span class="float-right{{if stringInSlice $addr $vin.Addresses}} text-danger{{end}}">{{formatAmount $vin.Value}} {{$cs}}</span>
{{end}}
{{- end -}}
</td>
</tr>
{{end}}
{{- end -}}
</tbody>
</table>
</div>
@ -41,27 +41,24 @@
<div class="row">
<table class="table data-table">
<tbody>
{{range $vout := $tx.Vout}}
{{- range $vout := $tx.Vout -}}
<tr>
<td>
{{range $a := $vout.ScriptPubKey.Addresses}}
{{- range $a := $vout.ScriptPubKey.Addresses -}}
<span class="ellipsis float-left">
{{if and (ne $a $addr) $vout.ScriptPubKey.Searchable}}<a href="/explorer/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
{{- if and (ne $a $addr) $vout.ScriptPubKey.Searchable}}<a href="/explorer/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
</span>
{{else}}
{{- else -}}
<span class="float-left">Unparsed address</span>
{{end}}
{{- end -}}
<span class="float-right{{if stringInSlice $addr $vout.ScriptPubKey.Addresses}} text-success{{end}}">
{{formatAmount $vout.Value}} {{$cs}}
{{if $vout.Spent}}
<span class="text-danger">(S)</span>
{{else}}
{{formatAmount $vout.Value}} {{$cs}}{{if $vout.Spent}}{{if $vout.SpentTxID}}<a class="text-danger" href="/explorer/tx/{{$vout.SpentTxID}}">(S)</a>{{else}}<span class="text-danger">(S)</span>{{end}}{{else -}}
<span class="text-success">(U)</span>
{{end}}
{{- end -}}
</span>
</td>
</tr>
{{end}}
{{- end -}}
</tbody>
</table>
</div>
@ -69,16 +66,16 @@
</div>
<div class="row line-top">
<div class="col-xs-6 col-sm-4 col-md-4">
{{if $tx.Fees}}
{{- if $tx.Fees -}}
<span class="txvalues txvalues-default">Fee: {{formatAmount $tx.Fees}} {{$cs}}</span>
{{end}}
{{- end -}}
</div>
<div class="col-xs-6 col-sm-8 col-md-8 text-right">
{{if $tx.Confirmations}}
{{- if $tx.Confirmations -}}
<span class="txvalues txvalues-success">{{$tx.Confirmations}} Confirmations</span>
{{else}}
{{- else -}}
<span class="txvalues txvalues-danger ng-hide">Unconfirmed Transaction!</span>
{{end}}
{{- end -}}
<span class="txvalues txvalues-primary">{{formatAmount $tx.ValueOut}} {{$cs}}</span>
</div>
</div>