Add support for DIVI (#228)
* Add Divi Project (DIVI) support * Remove PivX comments, add Divi RPC tests * Merge with latest Blockbook state * Fix permissions issue with automatic setup * Recreate integration tests with block 430894 * Remove GetBlockHeader test * Increase frequency of mempool sync
This commit is contained in:
parent
44a0e5823f
commit
d6375a19dd
@ -9,6 +9,7 @@ import (
|
||||
"blockbook/bchain/coins/dash"
|
||||
"blockbook/bchain/coins/dcr"
|
||||
"blockbook/bchain/coins/digibyte"
|
||||
"blockbook/bchain/coins/divi"
|
||||
"blockbook/bchain/coins/dogecoin"
|
||||
"blockbook/bchain/coins/eth"
|
||||
"blockbook/bchain/coins/flo"
|
||||
@ -97,6 +98,7 @@ func init() {
|
||||
BlockChainFactories["ZelCash"] = zec.NewZCashRPC
|
||||
BlockChainFactories["Ravencoin"] = ravencoin.NewRavencoinRPC
|
||||
BlockChainFactories["Ritocoin"] = ritocoin.NewRitocoinRPC
|
||||
BlockChainFactories["Divi"] = divi.NewDiviRPC
|
||||
}
|
||||
|
||||
// GetCoinNameFromConfig gets coin name and coin shortcut from config file
|
||||
|
||||
229
bchain/coins/divi/diviparser.go
Executable file
229
bchain/coins/divi/diviparser.go
Executable file
@ -0,0 +1,229 @@
|
||||
package divi
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"math/big"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
)
|
||||
|
||||
const (
|
||||
// MainnetMagic = "network messages so the messages can be identified to belong to a specific coin"
|
||||
// Source https://github.com/DiviProject/Divi/blob/master0/divi/src/chainparams.cpp#L128-L136
|
||||
MainnetMagic wire.BitcoinNet = 0x8f8da0df
|
||||
)
|
||||
|
||||
var (
|
||||
// MainNetParams = ???
|
||||
MainNetParams chaincfg.Params
|
||||
)
|
||||
|
||||
func init() {
|
||||
// DIVI mainnet Address encoding magics
|
||||
MainNetParams = chaincfg.MainNetParams
|
||||
MainNetParams.Net = MainnetMagic
|
||||
MainNetParams.PubKeyHashAddrID = []byte{30} // starting with 'D'
|
||||
MainNetParams.ScriptHashAddrID = []byte{13}
|
||||
MainNetParams.PrivateKeyID = []byte{212}
|
||||
}
|
||||
|
||||
// DivicoinParser handle
|
||||
type DivicoinParser struct {
|
||||
*btc.BitcoinParser
|
||||
baseparser *bchain.BaseParser
|
||||
BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
|
||||
}
|
||||
|
||||
// NewDiviParser returns new DivicoinParser instance
|
||||
func NewDiviParser(params *chaincfg.Params, c *btc.Configuration) *DivicoinParser {
|
||||
p := &DivicoinParser{
|
||||
BitcoinParser: btc.NewBitcoinParser(params, c),
|
||||
baseparser: &bchain.BaseParser{},
|
||||
}
|
||||
p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
|
||||
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
|
||||
return p
|
||||
}
|
||||
|
||||
// GetChainParams contains network parameters for the main Divi 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
|
||||
//}
|
||||
}
|
||||
|
||||
// ParseBlock parses raw block to our Block struct
|
||||
func (p *DivicoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
r := bytes.NewReader(b)
|
||||
w := wire.MsgBlock{}
|
||||
h := wire.BlockHeader{}
|
||||
err := h.Deserialize(r)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "Deserialize")
|
||||
}
|
||||
|
||||
if h.Version > 3 {
|
||||
// Skip past AccumulatorCheckpoint which was added in pivx block version 4
|
||||
r.Seek(32, io.SeekCurrent)
|
||||
}
|
||||
|
||||
err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "DecodeTransactions")
|
||||
}
|
||||
|
||||
txs := make([]bchain.Tx, len(w.Transactions))
|
||||
for ti, t := range w.Transactions {
|
||||
txs[ti] = p.TxFromMsgTx(t, false)
|
||||
}
|
||||
|
||||
return &bchain.Block{
|
||||
BlockHeader: bchain.BlockHeader{
|
||||
Size: len(b),
|
||||
Time: h.Timestamp.Unix(),
|
||||
},
|
||||
Txs: txs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PackTx packs transaction to byte array using protobuf
|
||||
func (p *DivicoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
|
||||
return p.baseparser.PackTx(tx, height, blockTime)
|
||||
}
|
||||
|
||||
// UnpackTx unpacks transaction from protobuf byte array
|
||||
func (p *DivicoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
||||
return p.baseparser.UnpackTx(buf)
|
||||
}
|
||||
|
||||
// ParseTx parses byte array containing transaction and returns Tx struct
|
||||
func (p *DivicoinParser) ParseTx(b []byte) (*bchain.Tx, error) {
|
||||
t := wire.MsgTx{}
|
||||
r := bytes.NewReader(b)
|
||||
if err := t.Deserialize(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx := p.TxFromMsgTx(&t, true)
|
||||
tx.Hex = hex.EncodeToString(b)
|
||||
return &tx, nil
|
||||
}
|
||||
|
||||
// TxFromMsgTx parses tx and adds handling for OP_ZEROCOINSPEND inputs
|
||||
func (p *DivicoinParser) TxFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.Tx {
|
||||
vin := make([]bchain.Vin, len(t.TxIn))
|
||||
for i, in := range t.TxIn {
|
||||
s := bchain.ScriptSig{
|
||||
Hex: hex.EncodeToString(in.SignatureScript),
|
||||
// missing: Asm,
|
||||
}
|
||||
|
||||
txid := in.PreviousOutPoint.Hash.String()
|
||||
|
||||
vin[i] = bchain.Vin{
|
||||
Txid: txid,
|
||||
Vout: in.PreviousOutPoint.Index,
|
||||
Sequence: in.Sequence,
|
||||
ScriptSig: s,
|
||||
}
|
||||
}
|
||||
vout := make([]bchain.Vout, len(t.TxOut))
|
||||
for i, out := range t.TxOut {
|
||||
addrs := []string{}
|
||||
if parseAddresses {
|
||||
addrs, _, _ = p.OutputScriptToAddressesFunc(out.PkScript)
|
||||
}
|
||||
s := bchain.ScriptPubKey{
|
||||
Hex: hex.EncodeToString(out.PkScript),
|
||||
Addresses: addrs,
|
||||
// missing: Asm,
|
||||
// missing: Type,
|
||||
}
|
||||
var vs big.Int
|
||||
vs.SetInt64(out.Value)
|
||||
vout[i] = bchain.Vout{
|
||||
ValueSat: vs,
|
||||
N: uint32(i),
|
||||
ScriptPubKey: s,
|
||||
}
|
||||
}
|
||||
tx := bchain.Tx{
|
||||
Txid: t.TxHash().String(),
|
||||
Version: t.Version,
|
||||
LockTime: t.LockTime,
|
||||
Vin: vin,
|
||||
Vout: vout,
|
||||
// skip: BlockHash,
|
||||
// skip: Confirmations,
|
||||
// skip: Time,
|
||||
// skip: Blocktime,
|
||||
}
|
||||
return tx
|
||||
}
|
||||
|
||||
// ParseTxFromJSON parses JSON message containing transaction and returns Tx struct
|
||||
func (p *DivicoinParser) ParseTxFromJSON(msg json.RawMessage) (*bchain.Tx, error) {
|
||||
var tx bchain.Tx
|
||||
err := json.Unmarshal(msg, &tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range tx.Vout {
|
||||
vout := &tx.Vout[i]
|
||||
// convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal
|
||||
vout.ValueSat, err = p.AmountToBigInt(vout.JsonValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vout.JsonValue = ""
|
||||
|
||||
if vout.ScriptPubKey.Addresses == nil {
|
||||
vout.ScriptPubKey.Addresses = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
return &tx, nil
|
||||
}
|
||||
|
||||
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
||||
func (p *DivicoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
||||
rv, s, _ := p.BitcoinOutputScriptToAddressesFunc(script)
|
||||
return rv, s, nil
|
||||
}
|
||||
|
||||
// GetAddrDescForUnknownInput = ???
|
||||
func (p *DivicoinParser) GetAddrDescForUnknownInput(tx *bchain.Tx, input int) bchain.AddressDescriptor {
|
||||
if len(tx.Vin) > input {
|
||||
scriptHex := tx.Vin[input].ScriptSig.Hex
|
||||
|
||||
if scriptHex != "" {
|
||||
script, _ := hex.DecodeString(scriptHex)
|
||||
return script
|
||||
}
|
||||
}
|
||||
|
||||
s := make([]byte, 10)
|
||||
return s
|
||||
}
|
||||
376
bchain/coins/divi/diviparser_test.go
Executable file
376
bchain/coins/divi/diviparser_test.go
Executable file
@ -0,0 +1,376 @@
|
||||
// +build unittest
|
||||
|
||||
package divi
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
c := m.Run()
|
||||
chaincfg.ResetParams()
|
||||
os.Exit(c)
|
||||
}
|
||||
|
||||
// Test getting the address details from the address hash
|
||||
|
||||
func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) {
|
||||
type args struct {
|
||||
address string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "P2PKH1",
|
||||
args: args{address: "DDSsBchWiVfvPVn6Ldp1nL7k4L77cSDqM7"},
|
||||
want: "76a9145b1d583a4c270f2f14be77b298f0a9c6df97471388ac",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
parser := NewDiviParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := parser.GetAddrDescFromAddress(tt.args.address)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetAddrDescFromAddress() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
h := hex.EncodeToString(got)
|
||||
if !reflect.DeepEqual(h, tt.want) {
|
||||
t.Errorf("GetAddrDescFromAddress() = %v, want %v", h, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetAddressesFromAddrDesc(t *testing.T) {
|
||||
type args struct {
|
||||
script string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
want2 bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Normal",
|
||||
args: args{script: "76a914cb1196fb1b98d04b0cb8d2ffde3c2de3eb83d9fe88ac"},
|
||||
want: []string{"DPepnMkaNHKCa6cQi7oBThrdiFEwSSYFzv"},
|
||||
want2: true,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
parser := NewDiviParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b, _ := hex.DecodeString(tt.args.script)
|
||||
got, got2, err := parser.GetAddressesFromAddrDesc(b)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetAddressesFromAddrDesc() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want)
|
||||
}
|
||||
if !reflect.DeepEqual(got2, tt.want2) {
|
||||
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test the packing and unpacking of raw transaction data
|
||||
|
||||
var (
|
||||
// Mint transaction
|
||||
testTx1 bchain.Tx
|
||||
testTxPacked1 = "0a20f7a5324866ba18058ab032196f34458d19f7ec5a4ac284670c3ef07bfa724644124201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0603de3d060101ffffffff010000000000000000000000000018aefd9ce905200028defb1832160a0c303364653364303630313031180028ffffffff0f3a0210004000"
|
||||
|
||||
// Normal transaction
|
||||
testTx2 bchain.Tx
|
||||
testTxPacked2 = "0a20eace41778a2940ff423b72a42033990eb5d6092810734a5806da6f3e5b34086412ea010100000001084b029489e1cddf726080c447c8a2b1d4bbe43024db31b8b19bc07585db9555010000006a473044022017422b9e3414d6233fa75f9eb7778469bebbb40686b0f7eb77d90a04c80149610220411f1063086fe205ea821ceb0de89e8158e202aba00f5ebb92b51f97381311fd012102ccb10a2f0603a0624b8708abefb5f4700631fc131c5de38b51e0359e2ffa7d1cffffffff03000000000000000000f260de1a580100001976a9145b1d583a4c270f2f14be77b298f0a9c6df97471388ac009ca6920c0000001976a914cb1196fb1b98d04b0cb8d2ffde3c2de3eb83d9fe88ac0000000018aefd9ce905200028defb183298010a0012205595db8575c09bb1b831db2430e4bbd4b1a2c847c4806072dfcde18994024b081801226a473044022017422b9e3414d6233fa75f9eb7778469bebbb40686b0f7eb77d90a04c80149610220411f1063086fe205ea821ceb0de89e8158e202aba00f5ebb92b51f97381311fd012102ccb10a2f0603a0624b8708abefb5f4700631fc131c5de38b51e0359e2ffa7d1c28ffffffff0f3a0210003a490a0601581ade60f210011a1976a9145b1d583a4c270f2f14be77b298f0a9c6df97471388ac222244445373426368576956667650566e364c6470316e4c376b344c3737635344714d373a480a050c92a69c0010021a1976a914cb1196fb1b98d04b0cb8d2ffde3c2de3eb83d9fe88ac2222445065706e4d6b614e484b436136635169376f425468726469464577535359467a764000"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testTx1 = bchain.Tx{
|
||||
Hex: "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0603de3d060101ffffffff0100000000000000000000000000",
|
||||
Txid: "f7a5324866ba18058ab032196f34458d19f7ec5a4ac284670c3ef07bfa724644",
|
||||
LockTime: 0,
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
Coinbase: "03de3d060101",
|
||||
Sequence: 4294967295,
|
||||
},
|
||||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(0),
|
||||
N: 0,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Blocktime: 1562853038,
|
||||
Time: 1562853038,
|
||||
}
|
||||
|
||||
testTx2 = bchain.Tx{
|
||||
Hex: "0100000001084b029489e1cddf726080c447c8a2b1d4bbe43024db31b8b19bc07585db9555010000006a473044022017422b9e3414d6233fa75f9eb7778469bebbb40686b0f7eb77d90a04c80149610220411f1063086fe205ea821ceb0de89e8158e202aba00f5ebb92b51f97381311fd012102ccb10a2f0603a0624b8708abefb5f4700631fc131c5de38b51e0359e2ffa7d1cffffffff03000000000000000000f260de1a580100001976a9145b1d583a4c270f2f14be77b298f0a9c6df97471388ac009ca6920c0000001976a914cb1196fb1b98d04b0cb8d2ffde3c2de3eb83d9fe88ac00000000",
|
||||
Txid: "eace41778a2940ff423b72a42033990eb5d6092810734a5806da6f3e5b340864",
|
||||
LockTime: 0,
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
ScriptSig: bchain.ScriptSig{
|
||||
Hex: "473044022017422b9e3414d6233fa75f9eb7778469bebbb40686b0f7eb77d90a04c80149610220411f1063086fe205ea821ceb0de89e8158e202aba00f5ebb92b51f97381311fd012102ccb10a2f0603a0624b8708abefb5f4700631fc131c5de38b51e0359e2ffa7d1c",
|
||||
},
|
||||
Txid: "5595db8575c09bb1b831db2430e4bbd4b1a2c847c4806072dfcde18994024b08",
|
||||
Vout: 1,
|
||||
Sequence: 4294967295,
|
||||
},
|
||||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(0),
|
||||
N: 0,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(1477919531250),
|
||||
N: 1,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a9145b1d583a4c270f2f14be77b298f0a9c6df97471388ac",
|
||||
Addresses: []string{
|
||||
"DDSsBchWiVfvPVn6Ldp1nL7k4L77cSDqM7",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(54000000000),
|
||||
N: 2,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a914cb1196fb1b98d04b0cb8d2ffde3c2de3eb83d9fe88ac",
|
||||
Addresses: []string{
|
||||
"DPepnMkaNHKCa6cQi7oBThrdiFEwSSYFzv",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Blocktime: 1562853038,
|
||||
Time: 1562853038,
|
||||
}
|
||||
}
|
||||
|
||||
func Test_PackTx(t *testing.T) {
|
||||
type args struct {
|
||||
tx bchain.Tx
|
||||
height uint32
|
||||
blockTime int64
|
||||
parser *DivicoinParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "divi-1",
|
||||
args: args{
|
||||
tx: testTx1,
|
||||
height: 409054,
|
||||
blockTime: 1562853038,
|
||||
parser: NewDiviParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "divi-2",
|
||||
args: args{
|
||||
tx: testTx2,
|
||||
height: 409054,
|
||||
blockTime: 1562853038,
|
||||
parser: NewDiviParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked2,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := tt.args.parser.PackTx(&tt.args.tx, tt.args.height, tt.args.blockTime)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("packTx() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
h := hex.EncodeToString(got)
|
||||
if !reflect.DeepEqual(h, tt.want) {
|
||||
t.Errorf("packTx() = %v, want %v", h, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_UnpackTx(t *testing.T) {
|
||||
type args struct {
|
||||
packedTx string
|
||||
parser *DivicoinParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *bchain.Tx
|
||||
want1 uint32
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "divi-1",
|
||||
args: args{
|
||||
packedTx: testTxPacked1,
|
||||
parser: NewDiviParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx1,
|
||||
want1: 409054,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "divi-2",
|
||||
args: args{
|
||||
packedTx: testTxPacked2,
|
||||
parser: NewDiviParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx2,
|
||||
want1: 409054,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b, _ := hex.DecodeString(tt.args.packedTx)
|
||||
got, got1, err := tt.args.parser.UnpackTx(b)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("unpackTx() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("unpackTx() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if got1 != tt.want1 {
|
||||
t.Errorf("unpackTx() got1 = %v, want %v", got1, tt.want1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Block test - looks for size, time, and transaction hashes
|
||||
|
||||
type testBlock struct {
|
||||
size int
|
||||
time int64
|
||||
tx []string
|
||||
}
|
||||
|
||||
var testParseBlockTxs = map[int]testBlock{
|
||||
407407: {
|
||||
size: 479,
|
||||
time: 1562753629,
|
||||
tx: []string{
|
||||
"3f8f01aec6717ede0e167f267fe486f18ddd25a13afd910dc1d41537aa1c6658",
|
||||
"b25224449d0f5266073876e924c4d6a4f127175aae151a66db6619e4ca41fe1d",
|
||||
},
|
||||
},
|
||||
409054: {
|
||||
size: 479,
|
||||
time: 1562853038,
|
||||
tx: []string{
|
||||
"f7a5324866ba18058ab032196f34458d19f7ec5a4ac284670c3ef07bfa724644",
|
||||
"eace41778a2940ff423b72a42033990eb5d6092810734a5806da6f3e5b340864",
|
||||
},
|
||||
},
|
||||
408074: {
|
||||
size: 1303,
|
||||
time: 1562794078,
|
||||
tx: []string{
|
||||
"bf0004680570d49eefab2ab806bd41f99587b6f3e65d1e0fb1d8e8f766f211f3",
|
||||
"8a334d86443d5e54d3d112b7ab4eff79ed0b879cbc62c580beee080b3c9e1142",
|
||||
"1ba350ba68b8db6af589136a85246c961694434ec2ffd1ad9c86831965b96932",
|
||||
"e05dcfece505455e8b4bcaeeb9ae1060fcf9c95ad1402c4fbd3b2c2bf1778683",
|
||||
"d3980118dedde2666d5bcd03ebf2c2d91ad6056404503afe0c37ed6cdd549f62",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func helperLoadBlock(t *testing.T, height int) []byte {
|
||||
name := fmt.Sprintf("block_dump.%d", height)
|
||||
path := filepath.Join("testdata", name)
|
||||
|
||||
d, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
d = bytes.TrimSpace(d)
|
||||
|
||||
b := make([]byte, hex.DecodedLen(len(d)))
|
||||
_, err = hex.Decode(b, d)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func TestParseBlock(t *testing.T) {
|
||||
p := NewDiviParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for height, tb := range testParseBlockTxs {
|
||||
b := helperLoadBlock(t, height)
|
||||
|
||||
blk, err := p.ParseBlock(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if blk.Size != tb.size {
|
||||
t.Errorf("ParseBlock() block size: got %d, want %d", blk.Size, tb.size)
|
||||
}
|
||||
|
||||
if blk.Time != tb.time {
|
||||
t.Errorf("ParseBlock() block time: got %d, want %d", blk.Time, tb.time)
|
||||
}
|
||||
|
||||
if len(blk.Txs) != len(tb.tx) {
|
||||
t.Errorf("ParseBlock() number of transactions: got %d, want %d", len(blk.Txs), len(tb.tx))
|
||||
}
|
||||
|
||||
for ti, tx := range tb.tx {
|
||||
if blk.Txs[ti].Txid != tx {
|
||||
t.Errorf("ParseBlock() transaction %d: got %s, want %s", ti, blk.Txs[ti].Txid, tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
bchain/coins/divi/divirpc.go
Executable file
60
bchain/coins/divi/divirpc.go
Executable file
@ -0,0 +1,60 @@
|
||||
package divi
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// DivicoinRPC is an interface to JSON-RPC bitcoind service.
|
||||
type DivicoinRPC struct {
|
||||
*btc.BitcoinRPC
|
||||
}
|
||||
|
||||
// NewDiviRPC returns new DivicoinRPC instance.
|
||||
func NewDiviRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
|
||||
b, err := btc.NewBitcoinRPC(config, pushHandler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &DivicoinRPC{
|
||||
b.(*btc.BitcoinRPC),
|
||||
}
|
||||
s.RPCMarshaler = btc.JSONMarshalerV1{}
|
||||
s.ChainConfig.SupportsEstimateFee = true
|
||||
s.ChainConfig.SupportsEstimateSmartFee = false
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Initialize initializes DivicoinRPC instance.
|
||||
func (b *DivicoinRPC) 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 = NewDiviParser(params, b.ChainConfig)
|
||||
|
||||
/* parameters for getInfo request
|
||||
-- can be added later
|
||||
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
|
||||
}
|
||||
1
bchain/coins/divi/testdata/block_dump.407407
vendored
Executable file
1
bchain/coins/divi/testdata/block_dump.407407
vendored
Executable file
@ -0,0 +1 @@
|
||||
04000000881f4e2a409a1b75c62ed6fdc6fa278b00f304bbe0729853bc336cbc30c4931da66efc4bd6260f95886061747185eace5294209dbe390fa3408534e42a0f5d525dba255dfe78101b0000000000000000000000000000000000000000000000000000000000000000000000000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff06036f37060101ffffffff01000000000000000000000000000100000001652779264ccc941129adb833b8a42a6d278a98f295d25a0a53868ab1dc13bed4020000006a473044022046c6ab760d25c7d94f20aa2c81cc281a57bb3fa174023dcaac385727ab05f214022056841e947398a1d86bf7d0b99191f7d3421d0abf6ad1357955d38f5fe6c3a8c40121023c85ccefc390984ba8f71a0f0b999b7b6c6e9a30ccd63087d67d34d5c1fefc7dffffffff0300000000000000000080170a4e830000001976a914771f45c78657c739f0cc26dfc0b5a87ddd6e431c88ac009ca6920c0000001976a914e7c53cbb09860c3713b44958dd644e4d9154345688ac00000000412066000b291e3e3fd8f1fce0812ba4aaad2502a702fd3466a3d8a7dc1a78c816be01209f1179d41f7d38da229f1843a9c19cf67a9d610c2a767979ea31b264f3eb
|
||||
1
bchain/coins/divi/testdata/block_dump.408074
vendored
Executable file
1
bchain/coins/divi/testdata/block_dump.408074
vendored
Executable file
@ -0,0 +1 @@
|
||||
040000000ff149a32a715106e7023cd41193d7ea64ca0092edb4659f035a881fc452b845e9249f2c4463db2074e307ba62e93619fd3d17a3b6b7437a326a79869f35c00c5e58265db760101b0000000000000000000000000000000000000000000000000000000000000000000000000501000000010000000000000000000000000000000000000000000000000000000000000000ffffffff06030a3a060101ffffffff01000000000000000000000000000100000001fdb6b4d9d9aa8afbdaac2d9bc4c29371147a6a3672529ad7ae45a7944558ec93020000006a473044022061bc3ffe2b069a39acdba6a169ae4fbaa34b32360ff9a45fce9c92eb0434ca6602206fa6c22110f4a14c8cee58e458e3522f41993e461278ef8ccb94322595981ec1012103b2e3a485f7a7da6eb16ea025ef45efa613d18350b2538899fab0b5a2e86ffda3ffffffff0300000000000000000000a882a22d0000001976a914899ef2e7669830485476f9c910a8330959d245e188ac009ca6920c0000001976a914a9147e5ce1507c2f49d9ceb8bbd2d280fb410b8188ac000000000100000002a0a25308b7afb81327a4a8cb1d13aa54fa53edf292bdf7fe2739f297f4027bb4000000006b4830450221009396b072158c158e7e90cdd797a0a58caf15c7e1589030d542a32e3568324a22022063d90727f3a71a9c01f75ece872ee0240f46eeac14531a7f2bfdb3fe5d0e793f01210263e67be5854349c3c8e23fea5020aa2b7bfd46916ce4e805676e4cd3b375cda5ffffffff8c7745969fbcd3bfb698d51cc8b110fe540d6a0ed9816bd2c1e375f0e7c2ec94000000006a4730440220748c808b1107ecf01559159c76163a2206af771604643aefea438f3c99c699a0022006c067c603fb0b4bc7a5cd129750fc010613957ec0666c41185d035b6f5fcbb1012102a535454382f62235104836bbbe1c894f1d6705c828b8be11f623068159882eb0ffffffff022018e505000000001976a914bba57e3d30f892d804d588ee633dcbb6a96b0cbb88ac0010a5d4e80000001976a914dd40b08afb0dc8496892bfe5e3ae1aceda57135b88ac000000000100000001583f174f32c563eb47555fbacdb0937881b4a25f35fe5f13d8c49cbf92654fdd000000006b483045022100cbacf5f775ab4fabdfb147c095c0865dd56bc461115b03a7a29ab96037fc4b3f02206b824c334b950d856550fff524717e07095fa2d9bbe8d5d8096813721d98715c012103f4e09f09921ad224e9e590df477cea01fc8114e816a2112ed59518bf99cdaa3effffffff0200f2052a010000001976a9148226210ccf912fb3969c0996a5582dcfb99a2e1788ac60b66daee00000001976a914d649408521dfef8449203417d77e44eadfc329f588ac00000000010000000199bd849243dea120d7d7df9037caa11327ed9df671e90c06442d12859ef4c052000000006a4730440220101b4e2022b3ffa023b83197d8ceb45b3ef31ff2da5eba7a6f7f914448397c31022023cb7908eafab080da4ff37460feb3c72e1ac6ecdb052d2df0c69a3954ec44550121026fd3594eb77ded5de88f54a528950659822859472fcee072a59657032aaf6fe2ffffffff02f071dee22c0000001976a914a316f474589a2f2013bd60b7d0ffb735e33915d188ac00e1823e0c0100001976a914ee628c1d309de0e0d3033d047b19921563f97ee288ac00000000411f3b6a2aabf7c3ccdd2e4d30a581a53670b6bc623e324eb3416100dfe64b3c54a84567bace9246f935b310e026c137eb7ec9836dfb46854aa6695af50a1ac5dd64
|
||||
1
bchain/coins/divi/testdata/block_dump.409054
vendored
Executable file
1
bchain/coins/divi/testdata/block_dump.409054
vendored
Executable file
@ -0,0 +1 @@
|
||||
04000000c7fed5984ba7d11c7e4865c1d41ad1755a1082782d81a27fc08888bc749881e9e709a5bb1daf5a76582def89c13eba5e7c4cf8104407ecf81f74be6ba18e89c6ae3e275da61b0d1b0000000000000000000000000000000000000000000000000000000000000000000000000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0603de3d060101ffffffff01000000000000000000000000000100000001084b029489e1cddf726080c447c8a2b1d4bbe43024db31b8b19bc07585db9555010000006a473044022017422b9e3414d6233fa75f9eb7778469bebbb40686b0f7eb77d90a04c80149610220411f1063086fe205ea821ceb0de89e8158e202aba00f5ebb92b51f97381311fd012102ccb10a2f0603a0624b8708abefb5f4700631fc131c5de38b51e0359e2ffa7d1cffffffff03000000000000000000f260de1a580100001976a9145b1d583a4c270f2f14be77b298f0a9c6df97471388ac009ca6920c0000001976a914cb1196fb1b98d04b0cb8d2ffde3c2de3eb83d9fe88ac00000000411f90bba5b16a087a5b7e0b8fc2aba041d81d74d270b502b24ea5801b5f4f975bba382260a6fd247facbb49acb8f304324deb3c1e00060d10a4958c047e4530c9fa
|
||||
65
configs/coins/divi.json
Normal file
65
configs/coins/divi.json
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
"coin": {
|
||||
"name": "Divi",
|
||||
"shortcut": "DIVI",
|
||||
"label": "Divi Project",
|
||||
"alias": "divi"
|
||||
},
|
||||
"ports": {
|
||||
"backend_rpc": 8089,
|
||||
"backend_message_queue": 38389,
|
||||
"blockbook_internal": 9089,
|
||||
"blockbook_public": 9189
|
||||
},
|
||||
"ipc": {
|
||||
"rpc_url_template": "http://127.0.0.1:{{.Ports.BackendRPC}}",
|
||||
"rpc_user": "divirpc",
|
||||
"rpc_pass": "divipass",
|
||||
"rpc_timeout": 25,
|
||||
"message_queue_binding_template": "tcp://127.0.0.1:{{.Ports.BackendMessageQueue}}"
|
||||
},
|
||||
"backend": {
|
||||
"package_name": "backend-divi",
|
||||
"package_revision": "satoshilabs-1",
|
||||
"system_user": "divi",
|
||||
"version": "1.0.4",
|
||||
"binary_url": "https://github.com/DiviProject/Divi/releases/download/v1.0.4-core/divi_ubuntu.zip",
|
||||
"extract_command": "unzip -j -d backend",
|
||||
"exclude_files": [
|
||||
"divi-cli",
|
||||
"divi-tx"
|
||||
],
|
||||
"exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/divid -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid",
|
||||
"logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/*.log",
|
||||
"postinst_script_template": "chmod a+x {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/divid",
|
||||
"service_type": "forking",
|
||||
"service_additional_params_template": "",
|
||||
"protect_memory": false,
|
||||
"mainnet": true,
|
||||
"server_config_file": "bitcoin_like.conf",
|
||||
"client_config_file": "bitcoin_like_client.conf",
|
||||
"additional_params": {
|
||||
"rpcallowip": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
"blockbook": {
|
||||
"package_name": "blockbook-divi",
|
||||
"system_user": "blockbook-divi",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "https://chainz.cryptoid.info/divi/",
|
||||
"additional_params": "-resyncindexperiod=30011 -resyncmempoolperiod=2011",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
"mempool_workers": 8,
|
||||
"mempool_sub_workers": 2,
|
||||
"block_addresses_to_keep": 300,
|
||||
"slip44": 301,
|
||||
"additional_params": {}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"package_maintainer": "James Scaur",
|
||||
"package_maintainer_email": "james@txbatch.com"
|
||||
}
|
||||
}
|
||||
@ -36,6 +36,7 @@
|
||||
| Flo | 9066 | 9166 | 8066 | 38366 |
|
||||
| Polis | 9067 | 9167 | 8067 | 38367 |
|
||||
| Qtum | 9088 | 9188 | 8088 | 38388 |
|
||||
| Divi Project | 9089 | 9189 | 8089 | 38389 |
|
||||
| Bitcoin Testnet | 19030 | 19130 | 18030 | 48330 |
|
||||
| Bitcoin Cash Testnet | 19031 | 19131 | 18031 | 48331 |
|
||||
| Zcash Testnet | 19032 | 19132 | 18032 | 48332 |
|
||||
|
||||
52
tests/rpc/testdata/divi.json
vendored
Normal file
52
tests/rpc/testdata/divi.json
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"blockHeight": 430894,
|
||||
"blockHash": "ca642b4cebd715d7448066e72d9c1c9f7cc17a7c7275ce5732357f9ede6199c7",
|
||||
"blockTime": 1564178016,
|
||||
"blockTxs": [
|
||||
"c206fc61c6957c54f365e7416d57a7cb314674b64aa84443ffa9b6d196aca9d9",
|
||||
"877557968ae65d64e99d09170cd9548e8a309508596355cc264758ce8c483b4b"
|
||||
],
|
||||
"txDetails": {
|
||||
"877557968ae65d64e99d09170cd9548e8a309508596355cc264758ce8c483b4b": {
|
||||
"hex": "010000000175d0b5235b4786be686a50f04382c3e401a1e8aa1ba17e7c959a58ddd39efeaa010000006b483045022100e552531d4be4290438edc7e8c5d1e2b5548c1a76cd396dfa9423b0e55abb0c6a02203efc3f76133de9161ba787c5fd9ef4cffbfd0745cfea8cf3a3f6dd3bce9293d0012103961c8f7574f64a61087adf3057f394be8bdc33b7a8abcbc60a71f7477dbd52a1ffffffff03000000000000000000009bb81da10100001976a9143ae7ad31dc26934c71e61bbb3248fb509a5f5d5988ac009ca6920c0000001976a9140d570e6e31e046f05b26f8bd8b14adbc2e76f99988ac00000000",
|
||||
"txid": "877557968ae65d64e99d09170cd9548e8a309508596355cc264758ce8c483b4b",
|
||||
"blocktime": 1564178016,
|
||||
"time": 1564178016,
|
||||
"locktime": 0,
|
||||
"version": 1,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "aafe9ed3dd589a957c7ea11baae8a101e4c38243f0506a68be86475b23b5d075",
|
||||
"vout": 1,
|
||||
"sequence": 4294967295,
|
||||
"scriptSig": {
|
||||
"hex": "483045022100e552531d4be4290438edc7e8c5d1e2b5548c1a76cd396dfa9423b0e55abb0c6a02203efc3f76133de9161ba787c5fd9ef4cffbfd0745cfea8cf3a3f6dd3bce9293d0012103961c8f7574f64a61087adf3057f394be8bdc33b7a8abcbc60a71f7477dbd52a1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"type": "nonstandard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 17915,
|
||||
"n": 1,
|
||||
"scriptPubKey": {
|
||||
"hex": "76a9143ae7ad31dc26934c71e61bbb3248fb509a5f5d5988ac"
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 540,
|
||||
"n": 2,
|
||||
"scriptPubKey": {
|
||||
"hex": "76a9140d570e6e31e046f05b26f8bd8b14adbc2e76f99988ac"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
112
tests/sync/testdata/divi.json
vendored
Normal file
112
tests/sync/testdata/divi.json
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
{
|
||||
"connectBlocks": {
|
||||
"syncRanges": [
|
||||
{
|
||||
"lower": 430894,
|
||||
"upper": 430894
|
||||
}
|
||||
],
|
||||
"blocks": {
|
||||
"430894": {
|
||||
"height": 430894,
|
||||
"hash": "ca642b4cebd715d7448066e72d9c1c9f7cc17a7c7275ce5732357f9ede6199c7",
|
||||
"noTxs": 2,
|
||||
"txDetails": [
|
||||
{
|
||||
"hex": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff06032e93060101ffffffff0100000000000000000000000000",
|
||||
"txid": "c206fc61c6957c54f365e7416d57a7cb314674b64aa84443ffa9b6d196aca9d9",
|
||||
"version": 1,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"coinbase": "032e93060101",
|
||||
"sequence": 4294967295
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.00000000,
|
||||
"valueSat": 0,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "",
|
||||
"hex": "",
|
||||
"type": "nonstandard"
|
||||
}
|
||||
}
|
||||
],
|
||||
"blockhash": "ca642b4cebd715d7448066e72d9c1c9f7cc17a7c7275ce5732357f9ede6199c7",
|
||||
"height": 430894,
|
||||
"confirmations": 1036,
|
||||
"time": 1564178016,
|
||||
"blocktime": 1564178016,
|
||||
"size": 66
|
||||
},
|
||||
{
|
||||
"hex": "010000000175d0b5235b4786be686a50f04382c3e401a1e8aa1ba17e7c959a58ddd39efeaa010000006b483045022100e552531d4be4290438edc7e8c5d1e2b5548c1a76cd396dfa9423b0e55abb0c6a02203efc3f76133de9161ba787c5fd9ef4cffbfd0745cfea8cf3a3f6dd3bce9293d0012103961c8f7574f64a61087adf3057f394be8bdc33b7a8abcbc60a71f7477dbd52a1ffffffff03000000000000000000009bb81da10100001976a9143ae7ad31dc26934c71e61bbb3248fb509a5f5d5988ac009ca6920c0000001976a9140d570e6e31e046f05b26f8bd8b14adbc2e76f99988ac00000000",
|
||||
"txid": "877557968ae65d64e99d09170cd9548e8a309508596355cc264758ce8c483b4b",
|
||||
"version": 1,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "aafe9ed3dd589a957c7ea11baae8a101e4c38243f0506a68be86475b23b5d075",
|
||||
"vout": 1,
|
||||
"scriptSig": {
|
||||
"asm": "3045022100e552531d4be4290438edc7e8c5d1e2b5548c1a76cd396dfa9423b0e55abb0c6a02203efc3f76133de9161ba787c5fd9ef4cffbfd0745cfea8cf3a3f6dd3bce9293d001 03961c8f7574f64a61087adf3057f394be8bdc33b7a8abcbc60a71f7477dbd52a1",
|
||||
"hex": "483045022100e552531d4be4290438edc7e8c5d1e2b5548c1a76cd396dfa9423b0e55abb0c6a02203efc3f76133de9161ba787c5fd9ef4cffbfd0745cfea8cf3a3f6dd3bce9293d0012103961c8f7574f64a61087adf3057f394be8bdc33b7a8abcbc60a71f7477dbd52a1"
|
||||
},
|
||||
"sequence": 4294967295
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.00000000,
|
||||
"valueSat": 0,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "",
|
||||
"hex": "",
|
||||
"type": "nonstandard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 17915.00000000,
|
||||
"valueSat": 1791500000000,
|
||||
"n": 1,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 3ae7ad31dc26934c71e61bbb3248fb509a5f5d59 OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a9143ae7ad31dc26934c71e61bbb3248fb509a5f5d5988ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"DAWZGZ2NSQHgDY7HWZCkZEHC9ya5kiJVQJ"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 540.00000000,
|
||||
"valueSat": 54000000000,
|
||||
"n": 2,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 0d570e6e31e046f05b26f8bd8b14adbc2e76f999 OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a9140d570e6e31e046f05b26f8bd8b14adbc2e76f99988ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"D6MdcXyHpuMTDSF6zLPLT2UmXHB2ZY5x37"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"blockhash": "ca642b4cebd715d7448066e72d9c1c9f7cc17a7c7275ce5732357f9ede6199c7",
|
||||
"height": 430894,
|
||||
"confirmations": 1037,
|
||||
"time": 1564178016,
|
||||
"blocktime": 1564178016,
|
||||
"size": 235
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,6 +51,11 @@
|
||||
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync",
|
||||
"EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"]
|
||||
},
|
||||
"divi": {
|
||||
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync",
|
||||
"EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight"],
|
||||
"sync": ["ConnectBlocksParallel", "ConnectBlocks"]
|
||||
},
|
||||
"dogecoin": {
|
||||
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync"],
|
||||
"sync": ["ConnectBlocksParallel", "ConnectBlocks"]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user