diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index 1deb839f..2e02db45 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -6,6 +6,7 @@ import ( "blockbook/bchain/coins/btc" "blockbook/bchain/coins/btg" "blockbook/bchain/coins/dash" + "blockbook/bchain/coins/digibyte" "blockbook/bchain/coins/dogecoin" "blockbook/bchain/coins/eth" "blockbook/bchain/coins/gamecredits" @@ -54,6 +55,7 @@ func init() { BlockChainFactories["Namecoin"] = namecoin.NewNamecoinRPC BlockChainFactories["Monacoin"] = monacoin.NewMonacoinRPC BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC + BlockChainFactories["DigiByte"] = digibyte.NewDigiByteRPC BlockChainFactories["Myriad"] = myriad.NewMyriadRPC BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC BlockChainFactories["Groestlcoin Testnet"] = grs.NewGroestlcoinRPC diff --git a/bchain/coins/digibyte/digibyteparser.go b/bchain/coins/digibyte/digibyteparser.go new file mode 100644 index 00000000..0d86308d --- /dev/null +++ b/bchain/coins/digibyte/digibyteparser.go @@ -0,0 +1,48 @@ +package digibyte + +import ( + "blockbook/bchain/coins/btc" + + "github.com/btcsuite/btcd/wire" + "github.com/jakm/btcutil/chaincfg" +) + +const ( + MainnetMagic wire.BitcoinNet = 0xdab6c3fa +) + +var ( + MainNetParams chaincfg.Params +) + +func init() { + MainNetParams = chaincfg.MainNetParams + MainNetParams.Net = MainnetMagic + MainNetParams.PubKeyHashAddrID = []byte{30} + MainNetParams.ScriptHashAddrID = []byte{63} + MainNetParams.Bech32HRPSegwit = "dgb" +} + +// DigiByteParser handle +type DigiByteParser struct { + *btc.BitcoinParser +} + +// NewDigiByteParser returns new VertcoinParser instance +func NewDigiByteParser(params *chaincfg.Params, c *btc.Configuration) *DigiByteParser { + return &DigiByteParser{BitcoinParser: btc.NewBitcoinParser(params, c)} +} + +// GetChainParams contains network parameters for the main DigiByte network +func GetChainParams(chain string) *chaincfg.Params { + if !chaincfg.IsRegistered(&chaincfg.MainNetParams) { + chaincfg.RegisterBitcoinParams() + } + if !chaincfg.IsRegistered(&MainNetParams) { + err := chaincfg.Register(&MainNetParams) + if err != nil { + panic(err) + } + } + return &MainNetParams +} diff --git a/bchain/coins/digibyte/digibyteparser_test.go b/bchain/coins/digibyte/digibyteparser_test.go new file mode 100644 index 00000000..a7ea9bbd --- /dev/null +++ b/bchain/coins/digibyte/digibyteparser_test.go @@ -0,0 +1,78 @@ +// +build unittest + +package digibyte + +import ( + "blockbook/bchain/coins/btc" + "encoding/hex" + "os" + "reflect" + "testing" + + "github.com/jakm/btcutil/chaincfg" +) + +func TestMain(m *testing.M) { + c := m.Run() + chaincfg.ResetParams() + os.Exit(c) +} + +func TestAddressToOutputScript_Mainnet(t *testing.T) { + type args struct { + address string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "pubkeyhash1", + args: args{address: "DFDe9ne77eEUKUijjG4EpDwW9vDxckGgHN"}, + want: "76a9146e8d4f7f0dfeb5d69b9a2cf914a1a2e276312b2188ac", + wantErr: false, + }, + { + name: "pubkeyhash2", + args: args{address: "DPUnoXeaSDnNtQTa7U3nEMTYBVgJ6wVgCh"}, + want: "76a914c92bc70927a752deb91cf0361dcdb60bdac6a1d588ac", + wantErr: false, + }, + // TODO - complete + // { + // name: "scripthash1", + // args: args{address: "36c8VAv74dPZZa4cFayb92hzozkPL4fBPe"}, + // want: "a91435ec06fa05f2d3b16e88cd7eda7651a10ca2e01987", + // wantErr: false, + // }, + // { + // name: "scripthash2", + // args: args{address: "38A1RNvbA5c9wNRfyLVn1FCH5TPKJVG8YR"}, + // want: "a91446eb90e002f137f05385896c882fe000cc2e967f87", + // wantErr: false, + // }, + // { + // name: "witness_v0_keyhash", + // args: args{address: "vtc1qd80qaputavyhtvszlz9zprueqch0qd003g520j"}, + // want: "001469de0e878beb0975b202f88a208f99062ef035ef", + // wantErr: false, + // }, + } + parser := NewDigiByteParser(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) + } + }) + } +} diff --git a/bchain/coins/digibyte/digibyterpc.go b/bchain/coins/digibyte/digibyterpc.go new file mode 100644 index 00000000..0cc47e9e --- /dev/null +++ b/bchain/coins/digibyte/digibyterpc.go @@ -0,0 +1,51 @@ +package digibyte + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + "encoding/json" + + "github.com/golang/glog" +) + +// DigiByteRPC is an interface to JSON-RPC bitcoind service. +type DigiByteRPC struct { + *btc.BitcoinRPC +} + +// NewDigiByteRPC returns new DigiByteRPC instance. +func NewDigiByteRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { + b, err := btc.NewBitcoinRPC(config, pushHandler) + if err != nil { + return nil, err + } + + s := &DigiByteRPC{ + b.(*btc.BitcoinRPC), + } + s.RPCMarshaler = btc.JSONMarshalerV2{} + s.ChainConfig.SupportsEstimateFee = false + + return s, nil +} + +// Initialize initializes DigiByteRPC instance. +func (b *DigiByteRPC) 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 = NewDigiByteParser(params, b.ChainConfig) + + b.Testnet = false + b.Network = "livenet" + + glog.Info("rpc: block chain ", params.Name) + + return nil +} diff --git a/configs/coins/digibyte.json b/configs/coins/digibyte.json new file mode 100644 index 00000000..07cb8c8a --- /dev/null +++ b/configs/coins/digibyte.json @@ -0,0 +1,64 @@ +{ + "coin": { + "name": "DigiByte", + "shortcut": "DGB", + "label": "DigiByte", + "alias": "digibyte" + }, + "ports": { + "backend_rpc": 8042, + "backend_message_queue": 38342, + "blockbook_internal": 9042, + "blockbook_public": 9142 + }, + "ipc": { + "rpc_url_template": "http://127.0.0.1:{{.Ports.BackendRPC}}", + "rpc_user": "rpc", + "rpc_pass": "rpc", + "rpc_timeout": 25, + "message_queue_binding_template": "tcp://127.0.0.1:{{.Ports.BackendMessageQueue}}" + }, + "backend": { + "package_name": "backend-digibyte", + "package_revision": "satoshilabs-1", + "system_user": "digibyte", + "version": "6.16.5.1", + "binary_url": "https://github.com/digibyte/digibyte/releases/download/v6.16.5.1/digibyte-6.16.5-x86_64-linux-gnu.tar.gz", + "verification_type": "sha256", + "verification_source": "dd6bed0228087fbb51f08be55cbc08a0e3251acfe1be3249b634447837ecd857", + "extract_command": "tar -C backend --strip 1 -xf", + "exclude_files": [ + "bin/digibyte-qt" + ], + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/digibyted -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": "", + "service_type": "forking", + "service_additional_params_template": "", + "protect_memory": true, + "mainnet": true, + "config_file": "bitcoin.conf", + "additional_params": { + "whitelist": "127.0.0.1" + } + }, + "blockbook": { + "package_name": "blockbook-digibyte", + "system_user": "blockbook-digibyte", + "internal_binding_template": ":{{.Ports.BlockbookInternal}}", + "public_binding_template": ":{{.Ports.BlockbookPublic}}", + "explorer_url": "", + "additional_params": "", + "block_chain": { + "parse": true, + "mempool_workers": 8, + "mempool_sub_workers": 2, + "block_addresses_to_keep": 300, + "additional_params": {} + } + }, + "meta": { + "package_maintainer": "Martin Boehm", + "package_maintainer_email": "martin.bohm@satoshilabs.com" + } +}