Refactor tx api

ethereum
Martin Boehm 2018-12-19 13:59:18 +01:00
parent e12641ae7d
commit 81e105dd4f
7 changed files with 79 additions and 63 deletions

View File

@ -74,44 +74,34 @@ func (a *Amount) AsBigInt() big.Int {
return big.Int(*a)
}
// ScriptSig contains input script
type ScriptSig struct {
Hex string `json:"hex,omitempty"`
Asm string `json:"asm,omitempty"`
}
// Vin contains information about single transaction input
type Vin struct {
Txid string `json:"txid,omitempty"`
Vout uint32 `json:"vout,omitempty"`
Sequence int64 `json:"sequence,omitempty"`
N int `json:"n"`
ScriptSig ScriptSig `json:"scriptSig"`
AddrDesc bchain.AddressDescriptor `json:"-"`
Addresses []string `json:"addresses"`
Searchable bool `json:"-"`
ValueSat *Amount `json:"value,omitempty"`
}
// ScriptPubKey contains output script and addresses derived from it
type ScriptPubKey struct {
Hex string `json:"hex,omitempty"`
Asm string `json:"asm,omitempty"`
AddrDesc bchain.AddressDescriptor `json:"-"`
Addresses []string `json:"addresses"`
Searchable bool `json:"-"`
Type string `json:"type,omitempty"`
}
// Vout contains information about single transaction output
type Vout struct {
ValueSat *Amount `json:"value,omitempty"`
N int `json:"n"`
ScriptPubKey ScriptPubKey `json:"scriptPubKey"`
Spent bool `json:"spent,omitempty"`
SpentTxID string `json:"spentTxId,omitempty"`
SpentIndex int `json:"spentIndex,omitempty"`
SpentHeight int `json:"spentHeight,omitempty"`
ValueSat *Amount `json:"value,omitempty"`
N int `json:"n"`
Spent bool `json:"spent,omitempty"`
SpentTxID string `json:"spentTxId,omitempty"`
SpentIndex int `json:"spentIndex,omitempty"`
SpentHeight int `json:"spentHeight,omitempty"`
Hex string `json:"hex,omitempty"`
Asm string `json:"asm,omitempty"`
AddrDesc bchain.AddressDescriptor `json:"-"`
Addresses []string `json:"addresses"`
Searchable bool `json:"-"`
Type string `json:"type,omitempty"`
}
// Erc20Token contains info about ERC20 token held by an address
@ -158,7 +148,7 @@ type Tx struct {
Time int64 `json:"time,omitempty"`
Blocktime int64 `json:"blocktime"`
Size int `json:"size,omitempty"`
ValueOutSat *Amount `json:"valueOut,omitempty"`
ValueOutSat *Amount `json:"value"`
ValueInSat *Amount `json:"valueIn,omitempty"`
FeesSat *Amount `json:"fees,omitempty"`
Hex string `json:"hex,omitempty"`

View File

@ -5,13 +5,19 @@ import (
"math/big"
)
// ScriptSigV1 is used for legacy api v1
type ScriptSigV1 struct {
Hex string `json:"hex,omitempty"`
Asm string `json:"asm,omitempty"`
}
// VinV1 is used for legacy api v1
type VinV1 struct {
Txid string `json:"txid"`
Vout uint32 `json:"vout"`
Sequence int64 `json:"sequence,omitempty"`
N int `json:"n"`
ScriptSig ScriptSig `json:"scriptSig"`
ScriptSig ScriptSigV1 `json:"scriptSig"`
AddrDesc bchain.AddressDescriptor `json:"-"`
Addresses []string `json:"addresses"`
Searchable bool `json:"-"`
@ -19,16 +25,26 @@ type VinV1 struct {
ValueSat big.Int `json:"-"`
}
// ScriptPubKeyV1 is used for legacy api v1
type ScriptPubKeyV1 struct {
Hex string `json:"hex,omitempty"`
Asm string `json:"asm,omitempty"`
AddrDesc bchain.AddressDescriptor `json:"-"`
Addresses []string `json:"addresses"`
Searchable bool `json:"-"`
Type string `json:"type,omitempty"`
}
// VoutV1 is used for legacy api v1
type VoutV1 struct {
Value string `json:"value"`
ValueSat big.Int `json:"-"`
N int `json:"n"`
ScriptPubKey ScriptPubKey `json:"scriptPubKey"`
Spent bool `json:"spent"`
SpentTxID string `json:"spentTxId,omitempty"`
SpentIndex int `json:"spentIndex,omitempty"`
SpentHeight int `json:"spentHeight,omitempty"`
Value string `json:"value"`
ValueSat big.Int `json:"-"`
N int `json:"n"`
ScriptPubKey ScriptPubKeyV1 `json:"scriptPubKey"`
Spent bool `json:"spent"`
SpentTxID string `json:"spentTxId,omitempty"`
SpentIndex int `json:"spentIndex,omitempty"`
SpentHeight int `json:"spentHeight,omitempty"`
}
// TxV1 is used for legacy api v1
@ -92,10 +108,13 @@ func (w *Worker) TxToV1(tx *Tx) *TxV1 {
for i := range tx.Vin {
v := &tx.Vin[i]
vinV1[i] = VinV1{
AddrDesc: v.AddrDesc,
Addresses: v.Addresses,
N: v.N,
ScriptSig: v.ScriptSig,
AddrDesc: v.AddrDesc,
Addresses: v.Addresses,
N: v.N,
ScriptSig: ScriptSigV1{
Asm: v.Asm,
Hex: v.Hex,
},
Searchable: v.Searchable,
Sequence: v.Sequence,
Txid: v.Txid,
@ -108,14 +127,21 @@ func (w *Worker) TxToV1(tx *Tx) *TxV1 {
for i := range tx.Vout {
v := &tx.Vout[i]
voutV1[i] = VoutV1{
N: v.N,
ScriptPubKey: v.ScriptPubKey,
Spent: v.Spent,
SpentHeight: v.SpentHeight,
SpentIndex: v.SpentIndex,
SpentTxID: v.SpentTxID,
Value: v.ValueSat.DecimalString(d),
ValueSat: v.ValueSat.AsBigInt(),
N: v.N,
ScriptPubKey: ScriptPubKeyV1{
AddrDesc: v.AddrDesc,
Addresses: v.Addresses,
Asm: v.Asm,
Hex: v.Hex,
Searchable: v.Searchable,
Type: v.Type,
},
Spent: v.Spent,
SpentHeight: v.SpentHeight,
SpentIndex: v.SpentIndex,
SpentTxID: v.SpentTxID,
Value: v.ValueSat.DecimalString(d),
ValueSat: v.ValueSat.AsBigInt(),
}
}
return &TxV1{

View File

@ -51,7 +51,7 @@ func (w *Worker) getAddressesFromVout(vout *bchain.Vout) (bchain.AddressDescript
// setSpendingTxToVout is helper function, that finds transaction that spent given output and sets it to the output
// there is no direct index for the operation, it must be found using addresses -> txaddresses -> tx
func (w *Worker) setSpendingTxToVout(vout *Vout, txid string, height uint32) error {
err := w.db.GetAddrDescTransactions(vout.ScriptPubKey.AddrDesc, height, ^uint32(0), func(t string, index int32, isOutput bool) error {
err := w.db.GetAddrDescTransactions(vout.AddrDesc, height, ^uint32(0), func(t string, index int32, isOutput bool) error {
if isOutput == false {
tsp, err := w.db.GetTxAddresses(t)
if err != nil {
@ -137,7 +137,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32,
vin.N = i
vin.Vout = bchainVin.Vout
vin.Sequence = int64(bchainVin.Sequence)
vin.ScriptSig.Hex = bchainVin.ScriptSig.Hex
vin.Hex = bchainVin.ScriptSig.Hex
if w.chainType == bchain.ChainBitcoinType {
// bchainVin.Txid=="" is coinbase transaction
if bchainVin.Txid != "" {
@ -195,8 +195,8 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32,
vout.N = i
vout.ValueSat = (*Amount)(&bchainVout.ValueSat)
valOutSat.Add(&valOutSat, &bchainVout.ValueSat)
vout.ScriptPubKey.Hex = bchainVout.ScriptPubKey.Hex
vout.ScriptPubKey.AddrDesc, vout.ScriptPubKey.Addresses, vout.ScriptPubKey.Searchable, err = w.getAddressesFromVout(bchainVout)
vout.Hex = bchainVout.ScriptPubKey.Hex
vout.AddrDesc, vout.Addresses, vout.Searchable, err = w.getAddressesFromVout(bchainVout)
if err != nil {
glog.V(2).Infof("getAddressesFromVout error %v, %v, output %v", err, bchainTx.Txid, bchainVout.N)
}
@ -205,7 +205,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32,
if spendingTxs && vout.Spent {
err = w.setSpendingTxToVout(vout, bchainTx.Txid, height)
if err != nil {
glog.Errorf("setSpendingTxToVout error %v, %v, output %v", err, vout.ScriptPubKey.AddrDesc, vout.N)
glog.Errorf("setSpendingTxToVout error %v, %v, output %v", err, vout.AddrDesc, vout.N)
}
}
}
@ -337,7 +337,7 @@ func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool
func (t *Tx) getAddrVoutValue(addrDesc bchain.AddressDescriptor) *big.Int {
var val big.Int
for _, vout := range t.Vout {
if bytes.Equal(vout.ScriptPubKey.AddrDesc, addrDesc) && vout.ValueSat != nil {
if bytes.Equal(vout.AddrDesc, addrDesc) && vout.ValueSat != nil {
val.Add(&val, (*big.Int)(vout.ValueSat))
}
}
@ -392,7 +392,7 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn
vout.N = i
vout.ValueSat = (*Amount)(&tao.ValueSat)
valOutSat.Add(&valOutSat, &tao.ValueSat)
vout.ScriptPubKey.Addresses, vout.ScriptPubKey.Searchable, err = tao.Addresses(w.chainParser)
vout.Addresses, vout.Searchable, err = tao.Addresses(w.chainParser)
if err != nil {
glog.Errorf("tai.Addresses error %v, tx %v, output %v, tao %+v", err, txid, i, tao)
}

View File

@ -397,7 +397,7 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
status: http.StatusOK,
contentType: "application/json; charset=utf-8",
body: []string{
`{"txid":"05e2e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":2,"n":0,"scriptSig":{},"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"value":"9876"}],"vout":[{"value":"9000","n":0,"scriptPubKey":{"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"]}}],"blockhash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockheight":225494,"confirmations":1,"time":22549400002,"blocktime":22549400002,"valueOut":"9000","valueIn":"9876","fees":"876"}`,
`{"txid":"05e2e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":2,"n":0,"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"value":"9876"}],"vout":[{"value":"9000","n":0,"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"]}],"blockhash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockheight":225494,"confirmations":1,"time":22549400002,"blocktime":22549400002,"value":"9000","valueIn":"9876","fees":"876"}`,
},
},
{

View File

@ -306,7 +306,7 @@ func txToResTx(tx *api.Tx) resTx {
for i := range tx.Vin {
vin := &tx.Vin[i]
txid := vin.Txid
script := vin.ScriptSig.Hex
script := vin.Hex
input := txInputs{
Txid: &txid,
Script: &script,
@ -323,13 +323,13 @@ func txToResTx(tx *api.Tx) resTx {
outputs := make([]txOutputs, len(tx.Vout))
for i := range tx.Vout {
vout := &tx.Vout[i]
script := vout.ScriptPubKey.Hex
script := vout.Hex
output := txOutputs{
Satoshis: (*big.Int)(vout.ValueSat).Int64(),
Script: &script,
}
if len(vout.ScriptPubKey.Addresses) > 0 {
a := vout.ScriptPubKey.Addresses[0]
if len(vout.Addresses) > 0 {
a := vout.Addresses[0]
output.Address = &a
}
outputs[i] = output
@ -412,7 +412,7 @@ func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res r
}
for i := range tx.Vout {
vout := &tx.Vout[i]
a := addressInSlice(vout.ScriptPubKey.Addresses, addr)
a := addressInSlice(vout.Addresses, addr)
if a != "" {
hi := ads[a]
if hi == nil {

View File

@ -24,7 +24,7 @@
{{if and (ne $a $addr) $vin.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
</span>
{{- else -}}
<span class="float-left">{{- if $vin.ScriptSig.Hex -}}Unparsed address{{- else -}}No Inputs (Newly Generated Coins){{- end -}}</span>
<span class="float-left">{{- if $vin.Hex -}}Unparsed address{{- else -}}No Inputs (Newly Generated Coins){{- end -}}</span>
{{- end -}}{{- if $vin.Addresses -}}
<span class="float-right{{if stringInSlice $addr $vin.Addresses}} text-danger{{end}}">{{formatAmount $vin.ValueSat}} {{$cs}}</span>
{{- end -}}
@ -51,14 +51,14 @@
{{- range $vout := $tx.Vout -}}
<tr>
<td>
{{- range $a := $vout.ScriptPubKey.Addresses -}}
{{- range $a := $vout.Addresses -}}
<span class="ellipsis float-left">
{{- if and (ne $a $addr) $vout.ScriptPubKey.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
{{- if and (ne $a $addr) $vout.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
</span>
{{- else -}}
<span class="float-left">Unparsed address</span>
{{- end -}}
<span class="float-right{{if stringInSlice $addr $vout.ScriptPubKey.Addresses}} text-success{{end}}">
<span class="float-right{{if stringInSlice $addr $vout.Addresses}} text-success{{end}}">
{{formatAmount $vout.ValueSat}} {{$cs}} {{if $vout.Spent}}<a class="text-danger" href="{{if $vout.SpentTxID}}/tx/{{$vout.SpentTxID}}{{else}}/spending/{{$tx.Txid}}/{{$vout.N}}{{end}}" title="Spent"></a>{{else -}}
<span class="text-success" title="Unspent"> <b>×</b></span>
{{- end -}}

View File

@ -47,9 +47,9 @@
{{- range $vout := $tx.Vout -}}
<tr>
<td>
{{- range $a := $vout.ScriptPubKey.Addresses -}}
{{- range $a := $vout.Addresses -}}
<span class="ellipsis float-left">
{{- if and (ne $a $addr) $vout.ScriptPubKey.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
{{- if and (ne $a $addr) $vout.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
</span>
{{- else -}}
<span class="float-left">Unparsed address</span>