Merge branch 'namecoin'
This commit is contained in:
commit
e3cfa7cb88
@ -9,6 +9,7 @@ import (
|
||||
"blockbook/bchain/coins/dogecoin"
|
||||
"blockbook/bchain/coins/eth"
|
||||
"blockbook/bchain/coins/litecoin"
|
||||
"blockbook/bchain/coins/namecoin"
|
||||
"blockbook/bchain/coins/zec"
|
||||
"blockbook/common"
|
||||
"context"
|
||||
@ -40,6 +41,7 @@ func init() {
|
||||
blockChainFactories["Litecoin"] = litecoin.NewLitecoinRPC
|
||||
blockChainFactories["Litecoin Testnet"] = litecoin.NewLitecoinRPC
|
||||
blockChainFactories["Dogecoin"] = dogecoin.NewDogecoinRPC
|
||||
blockChainFactories["Namecoin"] = namecoin.NewNamecoinRPC
|
||||
}
|
||||
|
||||
// GetCoinNameFromConfig gets coin name from config file
|
||||
|
||||
@ -3,8 +3,8 @@ package btg
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
@ -72,19 +72,6 @@ func GetChainParams(chain string) *chaincfg.Params {
|
||||
}
|
||||
}
|
||||
|
||||
// minTxPayload is the minimum payload size for a transaction. Note
|
||||
// that any realistically usable transaction must have at least one
|
||||
// input or output, but that is a rule enforced at a higher layer, so
|
||||
// it is intentionally not included here.
|
||||
// Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
|
||||
// number of transaction outputs 1 byte + LockTime 4 bytes + min input
|
||||
// payload + min output payload.
|
||||
const minTxPayload = 10
|
||||
|
||||
// maxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const maxTxPerBlock = (wire.MaxBlockPayload / minTxPayload) + 1
|
||||
|
||||
// headerFixedLength is the length of fixed fields of a block (i.e. without solution)
|
||||
// see https://github.com/BTCGPU/BTCGPU/wiki/Technical-Spec#block-header
|
||||
const headerFixedLength = 44 + (chainhash.HashSize * 3)
|
||||
@ -98,7 +85,7 @@ func (p *BGoldParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
}
|
||||
|
||||
w := wire.MsgBlock{}
|
||||
err = decodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -129,31 +116,3 @@ func skipHeader(r io.ReadSeeker, pver uint32) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeTransactions(r io.Reader, pver uint32, enc wire.MessageEncoding, blk *wire.MsgBlock) error {
|
||||
txCount, err := wire.ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prevent more transactions than could possibly fit into a block.
|
||||
// It would be possible to cause memory exhaustion and panics without
|
||||
// a sane upper bound on this count.
|
||||
if txCount > maxTxPerBlock {
|
||||
str := fmt.Sprintf("too many transactions to fit into a block "+
|
||||
"[count %d, max %d]", txCount, maxTxPerBlock)
|
||||
return &wire.MessageError{Func: "btg.decodeTransactions", Description: str}
|
||||
}
|
||||
|
||||
blk.Transactions = make([]*wire.MsgTx, 0, txCount)
|
||||
for i := uint64(0); i < txCount; i++ {
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, pver, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blk.Transactions = append(blk.Transactions, &tx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -3,9 +3,8 @@ package dogecoin
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -50,21 +49,6 @@ func GetChainParams(chain string) *chaincfg.Params {
|
||||
}
|
||||
}
|
||||
|
||||
// minTxPayload is the minimum payload size for a transaction. Note
|
||||
// that any realistically usable transaction must have at least one
|
||||
// input or output, but that is a rule enforced at a higher layer, so
|
||||
// it is intentionally not included here.
|
||||
// Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
|
||||
// number of transaction outputs 1 byte + LockTime 4 bytes + min input
|
||||
// payload + min output payload.
|
||||
const minTxPayload = 10
|
||||
|
||||
// maxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const maxTxPerBlock = (wire.MaxBlockPayload / minTxPayload) + 1
|
||||
|
||||
const versionAuxpow = (1 << 8)
|
||||
|
||||
// ParseBlock parses raw block to our Block struct
|
||||
// it has special handling for Auxpow blocks that cannot be parsed by standard btc wire parser
|
||||
func (p *DogecoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
@ -75,57 +59,13 @@ func (p *DogecoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if (h.Version & versionAuxpow) != 0 {
|
||||
// skip Auxpow part of the block
|
||||
// https://github.com/dogecoin/dogecoin/blob/master/src/auxpow.h#L130
|
||||
// CMerkleTx CTransaction
|
||||
tx := wire.MsgTx{}
|
||||
err = tx.BtcDecode(r, 0, wire.WitnessEncoding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CMerkleTx uint256 hashBlock
|
||||
_, err = r.Seek(32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CMerkleTx std::vector<uint256> vMerkleBranch
|
||||
size, err := wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CMerkleTx int nIndex
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CAuxPow std::vector<uint256> vChainMerkleBranch;
|
||||
size, err = wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CAuxPow int nChainIndex;
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CAuxPow CPureBlockHeader parentBlock;
|
||||
ph := wire.BlockHeader{}
|
||||
err = ph.Deserialize(r)
|
||||
if err != nil {
|
||||
if (h.Version & utils.VersionAuxpow) != 0 {
|
||||
if err = utils.SkipAuxpow(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = decodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -137,31 +77,3 @@ func (p *DogecoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
|
||||
return &bchain.Block{Txs: txs}, nil
|
||||
}
|
||||
|
||||
func decodeTransactions(r io.Reader, pver uint32, enc wire.MessageEncoding, blk *wire.MsgBlock) error {
|
||||
txCount, err := wire.ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prevent more transactions than could possibly fit into a block.
|
||||
// It would be possible to cause memory exhaustion and panics without
|
||||
// a sane upper bound on this count.
|
||||
if txCount > maxTxPerBlock {
|
||||
str := fmt.Sprintf("too many transactions to fit into a block "+
|
||||
"[count %d, max %d]", txCount, maxTxPerBlock)
|
||||
return &wire.MessageError{Func: "btg.decodeTransactions", Description: str}
|
||||
}
|
||||
|
||||
blk.Transactions = make([]*wire.MsgTx, 0, txCount)
|
||||
for i := uint64(0); i < txCount; i++ {
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, pver, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blk.Transactions = append(blk.Transactions, &tx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
79
bchain/coins/namecoin/namecoinparser.go
Normal file
79
bchain/coins/namecoin/namecoinparser.go
Normal file
@ -0,0 +1,79 @@
|
||||
package namecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
const (
|
||||
MainnetMagic wire.BitcoinNet = 0xfeb4bef9
|
||||
)
|
||||
|
||||
var (
|
||||
MainNetParams chaincfg.Params
|
||||
)
|
||||
|
||||
func init() {
|
||||
MainNetParams = chaincfg.MainNetParams
|
||||
MainNetParams.Net = MainnetMagic
|
||||
MainNetParams.PubKeyHashAddrID = 52
|
||||
MainNetParams.ScriptHashAddrID = 13
|
||||
|
||||
err := chaincfg.Register(&MainNetParams)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// NamecoinParser handle
|
||||
type NamecoinParser struct {
|
||||
*btc.BitcoinParser
|
||||
}
|
||||
|
||||
// NewNamecoinParser returns new NamecoinParser instance
|
||||
func NewNamecoinParser(params *chaincfg.Params, c *btc.Configuration) *NamecoinParser {
|
||||
return &NamecoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
|
||||
}
|
||||
|
||||
// GetChainParams contains network parameters for the main Namecoin network,
|
||||
// and the test Namecoin network
|
||||
func GetChainParams(chain string) *chaincfg.Params {
|
||||
switch chain {
|
||||
default:
|
||||
return &MainNetParams
|
||||
}
|
||||
}
|
||||
|
||||
// ParseBlock parses raw block to our Block struct
|
||||
// it has special handling for Auxpow blocks that cannot be parsed by standard btc wire parser
|
||||
func (p *NamecoinParser) 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, err
|
||||
}
|
||||
if (h.Version & utils.VersionAuxpow) != 0 {
|
||||
if err = utils.SkipAuxpow(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txs := make([]bchain.Tx, len(w.Transactions))
|
||||
for ti, t := range w.Transactions {
|
||||
txs[ti] = p.TxFromMsgTx(t, false)
|
||||
}
|
||||
|
||||
return &bchain.Block{Txs: txs}, nil
|
||||
}
|
||||
103
bchain/coins/namecoin/namecoinparser_test.go
Normal file
103
bchain/coins/namecoin/namecoinparser_test.go
Normal file
@ -0,0 +1,103 @@
|
||||
package namecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAddressToOutputScript_Mainnet(t *testing.T) {
|
||||
type args struct {
|
||||
address string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "P2PKH1",
|
||||
args: args{address: "MzBvZ4F759X6wHTjzwkMEbKh12am3PHT6F"},
|
||||
want: "76a91427a1f12771de5cc3b73941664b2537c15316be4388ac",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "P2PKH2",
|
||||
args: args{address: "N8Jkcm44Uq55GdmPojkpuGyoW4Cm658TwW"},
|
||||
want: "76a91480ad90d403581fa3bf46086a91b2d9d4125db6c188ac",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
parser := NewNamecoinParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := parser.AddressToOutputScript(tt.args.address)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("AddressToOutputScript() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
h := hex.EncodeToString(got)
|
||||
if !reflect.DeepEqual(h, tt.want) {
|
||||
t.Errorf("AddressToOutputScript() = %v, want %v", h, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var testParseBlockTxs = map[int][]string{
|
||||
40000: []string{
|
||||
"e193a821393b20b99f4a4e05a481368ef8a8cfd43d0c45bdad7f53bc9535e844",
|
||||
"ddcbf95797e81dd04127885bd001e96695b717e11c52721f6e8ee53f6dea8a6f",
|
||||
"31ff728f24200f59fa4958e6c26de03d172b320e6eef2b8abecf6f94d01dd4ae",
|
||||
},
|
||||
}
|
||||
|
||||
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 := NewNamecoinParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for height, txs := range testParseBlockTxs {
|
||||
b := helperLoadBlock(t, height)
|
||||
|
||||
blk, err := p.ParseBlock(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(blk.Txs) != len(txs) {
|
||||
t.Errorf("ParseBlock() number of transactions: got %d, want %d", len(blk.Txs), len(txs))
|
||||
}
|
||||
|
||||
for ti, tx := range txs {
|
||||
if blk.Txs[ti].Txid != tx {
|
||||
t.Errorf("ParseBlock() transaction %d: got %s, want %s", ti, blk.Txs[ti].Txid, tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
76
bchain/coins/namecoin/namecoinrpc.go
Normal file
76
bchain/coins/namecoin/namecoinrpc.go
Normal file
@ -0,0 +1,76 @@
|
||||
package namecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// NamecoinRPC is an interface to JSON-RPC namecoin service.
|
||||
type NamecoinRPC struct {
|
||||
*btc.BitcoinRPC
|
||||
}
|
||||
|
||||
// NewNamecoinRPC returns new NamecoinRPC instance.
|
||||
func NewNamecoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
|
||||
b, err := btc.NewBitcoinRPC(config, pushHandler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &NamecoinRPC{
|
||||
b.(*btc.BitcoinRPC),
|
||||
}
|
||||
s.RPCMarshaler = btc.JSONMarshalerV1{}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Initialize initializes NamecoinRPC instance.
|
||||
func (b *NamecoinRPC) Initialize() error {
|
||||
chainName, err := b.GetChainInfoAndInitializeMempool(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
glog.Info("Chain name ", chainName)
|
||||
params := GetChainParams(chainName)
|
||||
|
||||
// always create parser
|
||||
b.Parser = NewNamecoinParser(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
|
||||
}
|
||||
|
||||
// GetBlock returns block with given hash.
|
||||
func (b *NamecoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
|
||||
var err error
|
||||
if hash == "" {
|
||||
hash, err = b.GetBlockHash(height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if !b.ParseBlocks {
|
||||
return b.GetBlockFull(hash)
|
||||
}
|
||||
return b.GetBlockWithoutHeader(hash, height)
|
||||
}
|
||||
|
||||
// EstimateSmartFee returns fee estimation.
|
||||
func (b *NamecoinRPC) EstimateSmartFee(blocks int, conservative bool) (float64, error) {
|
||||
return b.EstimateFee(blocks)
|
||||
}
|
||||
1
bchain/coins/namecoin/testdata/block_dump.40000
vendored
Normal file
1
bchain/coins/namecoin/testdata/block_dump.40000
vendored
Normal file
@ -0,0 +1 @@
|
||||
0101010097d1d2cc478b4133407fc1ad4d8c8933b6c609b4ad32ddc4847bc25915cf2fe262408198c85ce883099de301b529280bd925791e3cad9404135dacee2f0d4250bd87234f8780201a0000000001000000010000000000000000000000000000000000000000000000000000000000000000ffffffff49043fd40c1a02a045122f503253482f42495031362f736c7573682f522cfabe6d6d40b41e94828aee66c19918b4da58a8d172329d321390ee9d260f7988402aa7b80100000000000000ffffffff0100f2052a01000000434104d31303d99295c26106241ba05bd4f0cf8019f0e2d23eb974b19b3eb13299d15e40c483af4517c8351307965d48697623e2b1a694ddff9a6d87d3ed349c1a1777ac00000000688dfcc6adf63446c8730082fa891ea665619311f4b409c4ec1800000000000004424a004f96a7100aed62e4f864c8d9234ef13bc8ceec263dbed155788c819552e72db83155702b8876691c102e598b8c7a94a32db86a54a8a47327ec2010ff2282939c62b3b1c218535a06c7912c3661c7074802d48e2d92b59acaba1f064c6e3f5352dc79864c6d856220657538a996835960ceedadc231a0ee376008d4b58d00000000000000000001000000fd28a68536508d85160396eb7341aa24749702d0c5db994d1e070000000000004e109c00dceed1da22ee7190fa9d7ad209ceb20c128ea7ce8a8cfb4befae011dc888234f3fd40c1a36d24c8d0301000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08048780201a010152ffffffff01a078072a01000000434104e926558cfefc8bc7fb256b681ee0edf15565c6174549b7f1293fcc0be208ed86f1a14cc18ea94ffa9c52b171d81f1d1efed00941bafeab92cc251c2d2aa345a3ac000000000071000002a93033530122276984f390bb2f974e1a7ff8da5f1be917838fa7b0352aa47678010000008b48304502201a1c6a80a0f0a3c5ea73be2b72d1f430e9eff43b6af4c735dc4ba6acd616640f022100a6680fbe27215365015007470d8bd6f38b49110916244eff5734a30124ef842901410499891bc83f6cf8aa1e538fa24320c072105753c078edcbbd8ce672c6eda9d94fc0aa38bf9b07cc6a3390bc0d7753a285f31eafc4c3dfdfbea00b492cb24f6ac5ffffffffa93033530122276984f390bb2f974e1a7ff8da5f1be917838fa7b0352aa476780000000049483045022100b43dbe3306698000cbb760947b31c99e87479861c208434db9dae8261479bd1f022054f044785dd0e67d71b7dd8d0bc0eb92b112436352d441854c550b80a62d8bb201ffffffff0340420f00000000003e520e467574726f6e204e75636c656172094cdb42c80c00f697000852455345525645446d6d76a914053a73e0c100ae994c6cd5cb128930bf0c33eb2d88ac802a645f0000000043410480294ad87bc7bad362df1c244048bc5e767004898acf42066366e4e191d2d485935f179aaa6247c614a0403d6ca4deefd86d076a23616c5a4c957c5231a99c87ac00093d0000000000016a0000000000710000016f8aea6d3fe58e6e1f72521ce117b79566e901d05b882741d01de89757f9cbdd010000004a493046022100ec16ef5125b67272706305419077bc40b849f84610624bf744ff1b1498d0cb29022100979407f7378eb5e2beff9f5a952410e7f4a4581182ccafcbcd73aecd9ded1e8f01ffffffff02f024545f000000004341047ffb631e4f525c756bf21225845cd7cdd7736151da56db362dac829a7d8de9789deba832d88e5a943036c3221156dc28224636669ef6c5865451a41aa5ebfc37ac40420f000000000030511426dc02d4a5aaeeab17e1872c761f3cca247c00896d76a9141728f2e7af41221eb00a7fa373cc0630afd382ea88ac00000000
|
||||
@ -1,8 +1,9 @@
|
||||
package zec
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
|
||||
"github.com/btcsuite/btcutil/base58"
|
||||
)
|
||||
|
||||
105
bchain/coins/utils/parserutils.go
Normal file
105
bchain/coins/utils/parserutils.go
Normal file
@ -0,0 +1,105 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// minTxPayload is the minimum payload size for a transaction. Note
|
||||
// that any realistically usable transaction must have at least one
|
||||
// input or output, but that is a rule enforced at a higher layer, so
|
||||
// it is intentionally not included here.
|
||||
// Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
|
||||
// number of transaction outputs 1 byte + LockTime 4 bytes + min input
|
||||
// payload + min output payload.
|
||||
const minTxPayload = 10
|
||||
|
||||
// maxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const maxTxPerBlock = (wire.MaxBlockPayload / minTxPayload) + 1
|
||||
|
||||
// DecodeTransactions decodes transactions from input stream using wire
|
||||
func DecodeTransactions(r io.Reader, pver uint32, enc wire.MessageEncoding, blk *wire.MsgBlock) error {
|
||||
txCount, err := wire.ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prevent more transactions than could possibly fit into a block.
|
||||
// It would be possible to cause memory exhaustion and panics without
|
||||
// a sane upper bound on this count.
|
||||
if txCount > maxTxPerBlock {
|
||||
str := fmt.Sprintf("too many transactions to fit into a block "+
|
||||
"[count %d, max %d]", txCount, maxTxPerBlock)
|
||||
return &wire.MessageError{Func: "btg.decodeTransactions", Description: str}
|
||||
}
|
||||
|
||||
blk.Transactions = make([]*wire.MsgTx, 0, txCount)
|
||||
for i := uint64(0); i < txCount; i++ {
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, pver, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blk.Transactions = append(blk.Transactions, &tx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VersionAuxpow marks that block contains Auxpow
|
||||
const VersionAuxpow = (1 << 8)
|
||||
|
||||
// SkipAuxpow skips Auxpow data in block
|
||||
func SkipAuxpow(r io.ReadSeeker) error {
|
||||
// skip Auxpow part of the block
|
||||
// https://github.com/dogecoin/dogecoin/blob/master/src/auxpow.h#L130
|
||||
// CMerkleTx CTransaction
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, 0, wire.WitnessEncoding)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CMerkleTx uint256 hashBlock
|
||||
_, err = r.Seek(32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CMerkleTx std::vector<uint256> vMerkleBranch
|
||||
size, err := wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CMerkleTx int nIndex
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CAuxPow std::vector<uint256> vChainMerkleBranch;
|
||||
size, err = wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CAuxPow int nChainIndex;
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CAuxPow CPureBlockHeader parentBlock;
|
||||
ph := wire.BlockHeader{}
|
||||
err = ph.Deserialize(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -3,6 +3,7 @@ package zec
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -54,12 +55,12 @@ func (p *ZCashParser) GetAddrIDFromVout(output *bchain.Vout) ([]byte, error) {
|
||||
if len(output.ScriptPubKey.Addresses) != 1 {
|
||||
return nil, nil
|
||||
}
|
||||
hash, _, err := CheckDecode(output.ScriptPubKey.Addresses[0])
|
||||
hash, _, err := utils.CheckDecode(output.ScriptPubKey.Addresses[0])
|
||||
return hash, err
|
||||
}
|
||||
|
||||
// GetAddrIDFromAddress returns internal address representation of given address
|
||||
func (p *ZCashParser) GetAddrIDFromAddress(address string) ([]byte, error) {
|
||||
hash, _, err := CheckDecode(address)
|
||||
hash, _, err := utils.CheckDecode(address)
|
||||
return hash, err
|
||||
}
|
||||
|
||||
1
build/deb/debian/blockbook-namecoin.conffiles
Normal file
1
build/deb/debian/blockbook-namecoin.conffiles
Normal file
@ -0,0 +1 @@
|
||||
/opt/coins/blockbook/namecoin/config/blockchaincfg.json
|
||||
2
build/deb/debian/blockbook-namecoin.cron.daily
Normal file
2
build/deb/debian/blockbook-namecoin.cron.daily
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
/opt/coins/blockbook/namecoin/bin/logrotate.sh
|
||||
2
build/deb/debian/blockbook-namecoin.dirs
Normal file
2
build/deb/debian/blockbook-namecoin.dirs
Normal file
@ -0,0 +1,2 @@
|
||||
/opt/coins/data/namecoin/blockbook
|
||||
/opt/coins/blockbook/namecoin/logs
|
||||
6
build/deb/debian/blockbook-namecoin.install
Executable file
6
build/deb/debian/blockbook-namecoin.install
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/dh-exec
|
||||
blockbook /opt/coins/blockbook/namecoin/bin
|
||||
cert /opt/coins/blockbook/namecoin
|
||||
static /opt/coins/blockbook/namecoin
|
||||
configs/namecoin.json => /opt/coins/blockbook/namecoin/config/blockchaincfg.json
|
||||
logrotate.sh /opt/coins/blockbook/namecoin/bin
|
||||
2
build/deb/debian/blockbook-namecoin.links
Normal file
2
build/deb/debian/blockbook-namecoin.links
Normal file
@ -0,0 +1,2 @@
|
||||
/opt/coins/blockbook/namecoin/cert/testcert.crt /opt/coins/blockbook/namecoin/cert/blockbook.crt
|
||||
/opt/coins/blockbook/namecoin/cert/testcert.key /opt/coins/blockbook/namecoin/cert/blockbook.key
|
||||
23
build/deb/debian/blockbook-namecoin.postinst
Normal file
23
build/deb/debian/blockbook-namecoin.postinst
Normal file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
|
||||
configure)
|
||||
if ! id -u blockbook-namecoin &> /dev/null
|
||||
then
|
||||
useradd --system -M -U blockbook-namecoin -s /bin/false
|
||||
fi
|
||||
|
||||
for dir in /opt/coins/data/namecoin/blockbook /opt/coins/blockbook/namecoin/logs
|
||||
do
|
||||
if [ "$(stat -c '%U' $dir)" != "blockbook-namecoin" ]
|
||||
then
|
||||
chown -R blockbook-namecoin:blockbook-namecoin $dir
|
||||
fi
|
||||
done
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
||||
43
build/deb/debian/blockbook-namecoin.service
Normal file
43
build/deb/debian/blockbook-namecoin.service
Normal file
@ -0,0 +1,43 @@
|
||||
# It is not recommended to modify this file in-place, because it will
|
||||
# be overwritten during package upgrades. If you want to add further
|
||||
# options or overwrite existing ones then use
|
||||
# $ systemctl edit blockbook-namecoin.service
|
||||
# See "man systemd.service" for details.
|
||||
|
||||
[Unit]
|
||||
Description=Blockbook daemon (Namecoin mainnet)
|
||||
After=network.target
|
||||
Wants=backend-namecoin.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/opt/coins/blockbook/namecoin/bin/blockbook -blockchaincfg=/opt/coins/blockbook/namecoin/config/blockchaincfg.json -datadir=/opt/coins/data/namecoin/blockbook/db -sync -httpserver=:9039 -socketio=:9139 -certfile=/opt/coins/blockbook/namecoin/cert/blockbook -explorer=https://namecha.in/ -log_dir=/opt/coins/blockbook/namecoin/logs
|
||||
User=blockbook-namecoin
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
WorkingDirectory=/opt/coins/blockbook/namecoin
|
||||
|
||||
# Resource limits
|
||||
LimitNOFILE=500000
|
||||
|
||||
# Hardening measures
|
||||
####################
|
||||
|
||||
# Provide a private /tmp and /var/tmp.
|
||||
PrivateTmp=true
|
||||
|
||||
# Mount /usr, /boot/ and /etc read-only for the process.
|
||||
ProtectSystem=full
|
||||
|
||||
# Disallow the process and all of its children to gain
|
||||
# new privileges through execve().
|
||||
NoNewPrivileges=true
|
||||
|
||||
# Use a new /dev namespace only populated with API pseudo devices
|
||||
# such as /dev/null, /dev/zero and /dev/random.
|
||||
PrivateDevices=true
|
||||
|
||||
# Deny the creation of writable and executable memory mappings.
|
||||
MemoryDenyWriteExecute=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -79,3 +79,8 @@ Package: blockbook-dogecoin
|
||||
Architecture: amd64
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils, psmisc, backend-dogecoin
|
||||
Description: Satoshilabs blockbook server (Dogecoin mainnet)
|
||||
|
||||
Package: blockbook-namecoin
|
||||
Architecture: amd64
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils, psmisc, backend-namecoin
|
||||
Description: Satoshilabs blockbook server (Dogecoin mainnet)
|
||||
|
||||
12
configs/namecoin.json
Normal file
12
configs/namecoin.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"coin_name": "Namecoin",
|
||||
"rpcURL": "http://127.0.0.1:8039",
|
||||
"rpcUser": "rpc",
|
||||
"rpcPass": "rpc",
|
||||
"rpcTimeout": 25,
|
||||
"parse": true,
|
||||
"zeroMQBinding": "tcp://127.0.0.1:38339",
|
||||
"mempoolWorkers": 8,
|
||||
"mempoolSubWorkers": 2,
|
||||
"blockAddressesToKeep": 300
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
TARGETS = bitcoin zcash bcash ethereum bgold dash litecoin dogecoin
|
||||
TARGETS = bitcoin zcash bcash ethereum bgold dash litecoin dogecoin namecoin
|
||||
IMAGE = blockbook-backend-build-deb
|
||||
NO_CACHE = false
|
||||
|
||||
|
||||
13
contrib/backends/namecoin/Makefile
Normal file
13
contrib/backends/namecoin/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
NAMECOIN_VERSION := 0.13.99
|
||||
|
||||
all:
|
||||
wget https://namecoin.org/files/namecoin-core-${NAMECOIN_VERSION}-name-tab-beta1-notreproduced/namecoin-${NAMECOIN_VERSION}-x86_64-linux-gnu.tar.gz
|
||||
tar -xf namecoin-${NAMECOIN_VERSION}-x86_64-linux-gnu.tar.gz
|
||||
mv namecoin-${NAMECOIN_VERSION} namecoin
|
||||
rm namecoin/bin/namecoin-qt
|
||||
rm namecoin/bin/test_namecoin*
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf namecoin
|
||||
rm -f namecoin-${NAMECOIN_VERSION}-x86_64-linux-gnu.tar.gz
|
||||
@ -0,0 +1 @@
|
||||
/opt/coins/nodes/namecoin/namecoin.conf
|
||||
1
contrib/backends/namecoin/debian/backend-namecoin.dirs
Normal file
1
contrib/backends/namecoin/debian/backend-namecoin.dirs
Normal file
@ -0,0 +1 @@
|
||||
/opt/coins/data/namecoin/backend
|
||||
@ -0,0 +1,2 @@
|
||||
namecoin/* /opt/coins/nodes/namecoin
|
||||
namecoin.conf /opt/coins/nodes/namecoin
|
||||
10
contrib/backends/namecoin/debian/backend-namecoin.logrotate
Normal file
10
contrib/backends/namecoin/debian/backend-namecoin.logrotate
Normal file
@ -0,0 +1,10 @@
|
||||
/opt/coins/data/namecoin/backend/debug.log
|
||||
/opt/coins/data/namecoin/backend/db.log
|
||||
{
|
||||
rotate 7
|
||||
daily
|
||||
compress
|
||||
missingok
|
||||
notifempty
|
||||
copytruncate
|
||||
}
|
||||
20
contrib/backends/namecoin/debian/backend-namecoin.postinst
Normal file
20
contrib/backends/namecoin/debian/backend-namecoin.postinst
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
|
||||
configure)
|
||||
if ! id -u namecoin &> /dev/null
|
||||
then
|
||||
useradd --system -M -U namecoin -s /bin/false
|
||||
fi
|
||||
|
||||
if [ "$(stat -c '%U' /opt/coins/data/namecoin/backend)" != "namecoin" ]
|
||||
then
|
||||
chown -R namecoin:namecoin /opt/coins/data/namecoin/backend
|
||||
fi
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
||||
47
contrib/backends/namecoin/debian/backend-namecoin.service
Normal file
47
contrib/backends/namecoin/debian/backend-namecoin.service
Normal file
@ -0,0 +1,47 @@
|
||||
# It is not recommended to modify this file in-place, because it will
|
||||
# be overwritten during package upgrades. If you want to add further
|
||||
# options or overwrite existing ones then use
|
||||
# $ systemctl edit namecoin.service
|
||||
# See "man systemd.service" for details.
|
||||
|
||||
# Note that almost all daemon options could be specified in
|
||||
# /opt/coins/nodes/namecoin/namecoin.conf
|
||||
|
||||
[Unit]
|
||||
Description=Namecoin daemon (mainnet)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/opt/coins/nodes/namecoin/bin/namecoind -datadir=/opt/coins/data/namecoin/backend -conf=/opt/coins/nodes/namecoin/namecoin.conf -pid=/run/namecoind/namecoin.pid
|
||||
# Creates /run/namecoind owned by namecoin
|
||||
RuntimeDirectory=namecoind
|
||||
User=namecoin
|
||||
Type=forking
|
||||
PIDFile=/run/namecoind/namecoin.pid
|
||||
Restart=on-failure
|
||||
|
||||
# Resource limits
|
||||
LimitNOFILE=500000
|
||||
|
||||
# Hardening measures
|
||||
####################
|
||||
|
||||
# Provide a private /tmp and /var/tmp.
|
||||
PrivateTmp=true
|
||||
|
||||
# Mount /usr, /boot/ and /etc read-only for the process.
|
||||
ProtectSystem=full
|
||||
|
||||
# Disallow the process and all of its children to gain
|
||||
# new privileges through execve().
|
||||
NoNewPrivileges=true
|
||||
|
||||
# Use a new /dev namespace only populated with API pseudo devices
|
||||
# such as /dev/null, /dev/zero and /dev/random.
|
||||
PrivateDevices=true
|
||||
|
||||
# Deny the creation of writable and executable memory mappings.
|
||||
# MemoryDenyWriteExecute=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
5
contrib/backends/namecoin/debian/changelog
Normal file
5
contrib/backends/namecoin/debian/changelog
Normal file
@ -0,0 +1,5 @@
|
||||
namecoin (0.13.99-satoshilabs1) unstable; urgency=medium
|
||||
|
||||
* Initial build
|
||||
|
||||
-- Martin Bohm <martin.bohm@satoshilabs.com> Mon, 18 Jun 2018 11:12:13 +0200
|
||||
1
contrib/backends/namecoin/debian/compat
Normal file
1
contrib/backends/namecoin/debian/compat
Normal file
@ -0,0 +1 @@
|
||||
9
|
||||
11
contrib/backends/namecoin/debian/control
Normal file
11
contrib/backends/namecoin/debian/control
Normal file
@ -0,0 +1,11 @@
|
||||
Source: namecoin
|
||||
Section: satoshilabs
|
||||
Priority: optional
|
||||
Maintainer: martin.bohm@satoshilabs.com
|
||||
Build-Depends: debhelper, wget, tar, gzip, make, dh-systemd, dh-exec
|
||||
Standards-Version: 3.9.5
|
||||
|
||||
Package: backend-namecoin
|
||||
Architecture: amd64
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, logrotate
|
||||
Description: Satoshilabs packaged namecoin server
|
||||
11
contrib/backends/namecoin/debian/rules
Executable file
11
contrib/backends/namecoin/debian/rules
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
DH_VERBOSE = 1
|
||||
|
||||
%:
|
||||
dh $@ --with=systemd
|
||||
|
||||
override_dh_systemd_start:
|
||||
dh_systemd_start --no-start
|
||||
|
||||
override_dh_installinit:
|
||||
23
contrib/backends/namecoin/namecoin.conf
Normal file
23
contrib/backends/namecoin/namecoin.conf
Normal file
@ -0,0 +1,23 @@
|
||||
daemon=1
|
||||
server=1
|
||||
nolisten=1
|
||||
rpcuser=rpc
|
||||
rpcpassword=rpc
|
||||
rpcport=8039
|
||||
txindex=1
|
||||
whitelist=127.0.0.1
|
||||
upnp=0
|
||||
discover=0
|
||||
whitelistrelay=1
|
||||
listenonion=0
|
||||
|
||||
addnode=45.24.110.177:8334
|
||||
|
||||
zmqpubhashtx=tcp://127.0.0.1:38339
|
||||
zmqpubhashblock=tcp://127.0.0.1:38339
|
||||
|
||||
rpcworkqueue=1100
|
||||
maxmempool=2000
|
||||
dbcache=1000
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user