Skip to content

Commit

Permalink
Merge branch 'guarda-changes' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeirbv committed Jan 11, 2021
2 parents 1d7e83f + 4188e73 commit b470346
Show file tree
Hide file tree
Showing 49 changed files with 2,885 additions and 69 deletions.
7 changes: 7 additions & 0 deletions README.md
Expand Up @@ -2,6 +2,8 @@

# Blockbook

**FOR INTERNAL GUARDA WALLET PURPOSES ONLY. PLEASE USE UPSTREAM INSTEAD!**

**Blockbook** is back-end service for Trezor wallet. Main features of **Blockbook** are:

- index of addresses and address balances of the connected block chain
Expand All @@ -11,6 +13,11 @@
- support of multiple coins (Bitcoin and Ethereum type), with easy extensibility for other coins
- scripts for easy creation of debian packages for backend and blockbook

## For Guarda Dev Team

- Branch `guarda-changes` only for production use. DO NOT MERGE UNTESTED CHANGES!
- Branch `master` for compability with Trezor upstream. ONLY PRs FROM UPSTREAM ALLOWED!

## Build and installation instructions

Officially supported platform is **Debian Linux** and **AMD64** architecture.
Expand Down
1 change: 1 addition & 0 deletions api/types.go
Expand Up @@ -281,6 +281,7 @@ type Utxo struct {
Path string `json:"path,omitempty"`
Locktime uint32 `json:"lockTime,omitempty"`
Coinbase bool `json:"coinbase,omitempty"`
ScriptPubKey string `json:"scriptPubKey,omitempty"`
}

// Utxos is array of Utxo
Expand Down
2 changes: 2 additions & 0 deletions api/typesv1.go
Expand Up @@ -92,6 +92,7 @@ type AddressUtxoV1 struct {
AmountSat big.Int `json:"satoshis"`
Height int `json:"height,omitempty"`
Confirmations int `json:"confirmations"`
ScriptPubKey string `json:"scriptPubKey"`
}

// BlockV1 contains information about block
Expand Down Expand Up @@ -205,6 +206,7 @@ func (w *Worker) AddressUtxoToV1(au Utxos) []AddressUtxoV1 {
Height: utxo.Height,
Txid: utxo.Txid,
Vout: uint32(utxo.Vout),
ScriptPubKey: utxo.ScriptPubKey,
}
}
return v1
Expand Down
91 changes: 86 additions & 5 deletions api/worker.go
Expand Up @@ -93,6 +93,19 @@ func (w *Worker) setSpendingTxToVout(vout *Vout, txid string, height uint32) err

// GetSpendingTxid returns transaction id of transaction that spent given output
func (w *Worker) GetSpendingTxid(txid string, n int) (string, error) {
if w.db.HasSpendingIndex() {
tsp, err := w.db.GetTxAddresses(txid)
if err != nil {
return "", err
} else if tsp == nil {
glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses")
return "", NewAPIError(fmt.Sprintf("Txid %v not found", txid), false)
}
if n >= len(tsp.Outputs) || n < 0 {
return "", NewAPIError(fmt.Sprintf("Passed incorrect vout index %v for tx %v, len vout %v", n, txid, len(tsp.Outputs)), false)
}
return tsp.Outputs[n].SpentTxid, nil
}
start := time.Now()
tx, err := w.GetTransaction(txid, false, false)
if err != nil {
Expand Down Expand Up @@ -144,6 +157,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
var pValInSat *big.Int
vins := make([]Vin, len(bchainTx.Vin))
rbf := false
var rawTxForInputValues *bchain.TxForInValues
for i := range bchainTx.Vin {
bchainVin := &bchainTx.Vin[i]
vin := &vins[i]
Expand Down Expand Up @@ -207,6 +221,28 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
if vin.ValueSat != nil {
valInSat.Add(&valInSat, (*big.Int)(vin.ValueSat))
}
} else {
vin.AddrDesc = w.chainParser.GetAddrDescForUnknownInput(bchainTx, i)
vin.Addresses, vin.IsAddress, err = w.chainParser.GetAddressesFromAddrDesc(vin.AddrDesc)
if rawTxForInputValues == nil {
rawTxJSON, err := w.chain.GetTransactionSpecific(bchainTx)
if err != nil {
glog.Error("Can't retrieve raw transaction with id ", bchainTx.Txid, ":", err)
}
if rawTxJSON != nil {
rawTxForInputValues = &bchain.TxForInValues{Vin: make([]bchain.VinValues, 0)}
err = json.Unmarshal(rawTxJSON, rawTxForInputValues)
}
}
if rawTxForInputValues != nil && rawTxForInputValues.Vin != nil && len(rawTxForInputValues.Vin) > i {
inputValue, err := w.chainParser.AmountToBigInt(rawTxForInputValues.Vin[i].Value)
if err == nil && inputValue.Cmp(big.NewInt(0)) != 0 {
vin.ValueSat = (*Amount)(&inputValue)
if vin.ValueSat != nil {
valInSat.Add(&valInSat, (*big.Int)(vin.ValueSat))
}
}
}
}
} else if w.chainType == bchain.ChainEthereumType {
if len(bchainVin.Addresses) > 0 {
Expand All @@ -233,10 +269,16 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
}
if ta != nil {
vout.Spent = ta.Outputs[i].Spent
if spendingTxs && vout.Spent {
err = w.setSpendingTxToVout(vout, bchainTx.Txid, uint32(height))
if err != nil {
glog.Errorf("setSpendingTxToVout error %v, %v, output %v", err, vout.AddrDesc, vout.N)
if vout.Spent {
if w.db.HasSpendingIndex() {
vout.SpentTxID = ta.Outputs[i].SpentTxid
vout.SpentIndex = int(ta.Outputs[i].SpentIndex)
vout.SpentHeight = int(ta.Outputs[i].SpentHeight)
} else if spendingTxs {
err = w.setSpendingTxToVout(vout, bchainTx.Txid, uint32(height))
if err != nil {
glog.Errorf("setSpendingTxToVout error %v, %v, output %v", err, vout.AddrDesc, vout.N)
}
}
}
}
Expand Down Expand Up @@ -547,6 +589,7 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn
var err error
var valInSat, valOutSat, feesSat big.Int
vins := make([]Vin, len(ta.Inputs))
var rawTxForInputValues *bchain.TxForInValues
for i := range ta.Inputs {
tai := &ta.Inputs[i]
vin := &vins[i]
Expand All @@ -555,7 +598,30 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn
valInSat.Add(&valInSat, &tai.ValueSat)
vin.Addresses, vin.IsAddress, err = tai.Addresses(w.chainParser)
if err != nil {
glog.Errorf("tai.Addresses error %v, tx %v, input %v, tai %+v", err, txid, i, tai)
//glog.Errorf("tai.Addresses error %v, tx %v, input %v, tai %+v", err, txid, i, tai)
} else {
if vin.Txid == "" {
if rawTxForInputValues == nil {
bchainTx, err := w.chain.GetTransaction(txid)
rawTxJSON, err := w.chain.GetTransactionSpecific(bchainTx)
if err != nil {
glog.Error("Can't retrieve raw transaction with id ", txid, ":", err)
}
if rawTxJSON != nil {
rawTxForInputValues = &bchain.TxForInValues{Vin: make([]bchain.VinValues, 0)}
err = json.Unmarshal(rawTxJSON, rawTxForInputValues)
}
}
if rawTxForInputValues != nil && rawTxForInputValues.Vin != nil && len(rawTxForInputValues.Vin) > i {
inputValue, err := w.chainParser.AmountToBigInt(rawTxForInputValues.Vin[i].Value)
if err == nil && inputValue.Cmp(big.NewInt(0)) != 0 {
vin.ValueSat = (*Amount)(&inputValue)
if vin.ValueSat != nil {
valInSat.Add(&valInSat, (*big.Int)(vin.ValueSat))
}
}
}
}
}
}
vouts := make([]Vout, len(ta.Outputs))
Expand All @@ -570,6 +636,11 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn
glog.Errorf("tai.Addresses error %v, tx %v, output %v, tao %+v", err, txid, i, tao)
}
vout.Spent = tao.Spent
if w.db.HasSpendingIndex() {
vout.SpentTxID = tao.SpentTxid
vout.SpentIndex = int(tao.SpentIndex)
vout.SpentHeight = int(tao.SpentHeight)
}
}
// for coinbase transactions valIn is 0
feesSat.Sub(&valInSat, &valOutSat)
Expand Down Expand Up @@ -1212,6 +1283,7 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
AmountSat: (*Amount)(&vout.ValueSat),
Locktime: bchainTx.LockTime,
Coinbase: coinbase,
ScriptPubKey: vout.ScriptPubKey.Hex,
})
inMempool[bchainTx.Txid] = struct{}{}
}
Expand Down Expand Up @@ -1259,6 +1331,14 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
coinbase = true
}
}
bchainTx, height, err := w.txCache.GetTransaction(txid)
if err != nil {
if err == bchain.ErrTxNotFound {
return nil, NewAPIError(fmt.Sprintf("Transaction '%v' not found", txid), true)
}
return nil, NewAPIError(fmt.Sprintf("Transaction '%v' not found (%v)", txid, err), true)
}
transaction, err := w.GetTransactionFromBchainTx(bchainTx, height, false, false)
_, e = inMempool[txid]
if !e {
utxos = append(utxos, Utxo{
Expand All @@ -1268,6 +1348,7 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
Height: int(utxo.Height),
Confirmations: confirmations,
Coinbase: coinbase,
ScriptPubKey: transaction.Vout[utxo.Vout].Hex,
})
}
}
Expand Down
64 changes: 64 additions & 0 deletions bchain/coins/aryacoin/aryacoinparser.go
@@ -0,0 +1,64 @@
package aryacoin

import (
"github.com/trezor/blockbook/bchain/coins/btc"

"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
)

// magic numbers
const (
MainnetMagic wire.BitcoinNet = 0xe7eae188
TestnetMagic wire.BitcoinNet = 0xf1c8d2fd
)

// chain parameters
var (
MainNetParams chaincfg.Params
TestNetParams chaincfg.Params
)

func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
MainNetParams.PubKeyHashAddrID = []byte{23}
MainNetParams.ScriptHashAddrID = []byte{5}
MainNetParams.Bech32HRPSegwit = "arya"

TestNetParams = chaincfg.TestNet3Params
TestNetParams.Net = TestnetMagic
TestNetParams.PubKeyHashAddrID = []byte{111}
TestNetParams.ScriptHashAddrID = []byte{196}
TestNetParams.Bech32HRPSegwit = "arya"
}

// AryaCoinParser handle
type AryaCoinParser struct {
*btc.BitcoinParser
}

// NewAryaCoinParser returns new AryaCoinParser instance
func NewAryaCoinParser(params *chaincfg.Params, c *btc.Configuration) *AryaCoinParser {
return &AryaCoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
}

// GetChainParams contains network parameters for the main AryaCoin network,
// and the test AryaCoin network
func GetChainParams(chain string) *chaincfg.Params {
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
switch chain {
case "test":
return &TestNetParams
default:
return &MainNetParams
}
}
58 changes: 58 additions & 0 deletions bchain/coins/aryacoin/aryacoinrpc.go
@@ -0,0 +1,58 @@
package aryacoin

import (
"github.com/trezor/blockbook/bchain"
"github.com/trezor/blockbook/bchain/coins/btc"
"encoding/json"

"github.com/golang/glog"
)

// AryaCoinRPC is an interface to JSON-RPC bitcoind service.
type AryaCoinRPC struct {
*btc.BitcoinRPC
}

// NewAryaCoinRPC returns new AryaCoinRPC instance.
func NewAryaCoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
b, err := btc.NewBitcoinRPC(config, pushHandler)
if err != nil {
return nil, err
}

s := &AryaCoinRPC{
BitcoinRPC: b.(*btc.BitcoinRPC),
}
s.RPCMarshaler = btc.JSONMarshalerV1{}
s.ChainConfig.SupportsEstimateFee = false

return s, nil
}

// Initialize initializes AryaCoinRPC instance.
func (b *AryaCoinRPC) Initialize() error {
ci, err := b.GetChainInfo()
if err != nil {
return err
}
chainName := ci.Chain

glog.Info("Chain name ", chainName)
params := GetChainParams(chainName)

// always create parser
b.Parser = NewAryaCoinParser(params, b.ChainConfig)

// parameters for getInfo request
if params.Net == MainnetMagic {
b.Testnet = false
b.Network = "livenet"
} else {
b.Testnet = true
b.Network = "testnet"
}

glog.Info("rpc: block chain ", params.Name)

return nil
}

0 comments on commit b470346

Please sign in to comment.