This commit is contained in:
Jeremiah Buddenhagen 2019-01-24 11:08:37 -08:00
parent 828a11b6c3
commit aad4f70f0c
7 changed files with 662 additions and 13 deletions

197
Gopkg.lock generated
View File

@ -3,217 +3,390 @@
[[projects]]
branch = "master"
digest = "1:8a2b12fb7e723619cc185b2ee1bad0b0c39e5791f0e576fc45e630242b5c5b7a"
name = "github.com/Groestlcoin/go-groestl-hash"
packages = ["groestl","hash"]
packages = [
"groestl",
"hash",
]
pruneopts = ""
revision = "790653ac190c4029ee200e82a8f21b5d1afaf7d6"
[[projects]]
branch = "master"
digest = "1:c0bec5f9b98d0bc872ff5e834fac186b807b656683bd29cb82fb207a1513fabb"
name = "github.com/beorn7/perks"
packages = ["quantile"]
pruneopts = ""
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
[[projects]]
branch = "master"
digest = "1:624a0f2b645f86d870e85d1875bae00313b295ea962be32627099efc9e57358f"
name = "github.com/bsm/go-vlq"
packages = ["."]
pruneopts = ""
revision = "ec6e8d4f5f4ec0f6e808ffc7f4dcc7516d4d7d49"
[[projects]]
branch = "master"
digest = "1:53af1aee2d9d8544de49a42d39c6da2ab656a03639781169d697419d42dbdbd5"
name = "github.com/btcsuite/btcd"
packages = ["blockchain","btcec","chaincfg","chaincfg/chainhash","database","txscript","wire"]
packages = [
"blockchain",
"btcec",
"chaincfg",
"chaincfg/chainhash",
"database",
"txscript",
"wire",
]
pruneopts = ""
revision = "2be2f12b358dc57d70b8f501b00be450192efbc3"
[[projects]]
branch = "master"
digest = "1:30d4a548e09bca4a0c77317c58e7407e2a65c15325e944f9c08a7b7992f8a59e"
name = "github.com/btcsuite/btclog"
packages = ["."]
pruneopts = ""
revision = "84c8d2346e9fc8c7b947e243b9c24e6df9fd206a"
[[projects]]
branch = "master"
digest = "1:827862daac23c3e946d7f0800957967e88e5d4b4b8437a303291237db3f565f3"
name = "github.com/btcsuite/btcutil"
packages = [".","base58","bech32"]
packages = [
".",
"base58",
"bech32",
]
pruneopts = ""
revision = "501929d3d046174c3d39f0ea54ece471aa17238c"
[[projects]]
digest = "1:c0243ca6ea596b1c547ae44d824fa42f9127af26788efaeb930898586d186c4d"
name = "github.com/deckarep/golang-set"
packages = ["."]
pruneopts = ""
revision = "1d4478f51bed434f1dadf96dcd9b43aabac66795"
version = "v1.7"
[[projects]]
digest = "1:8acdd83e35b407d026e546bf4d18cc778e9604433d03d468eccca62b9c51c718"
name = "github.com/ethereum/go-ethereum"
packages = [".","common","common/hexutil","common/math","core/types","crypto","crypto/secp256k1","crypto/sha3","ethclient","ethdb","log","metrics","p2p/netutil","params","rlp","rpc","trie"]
packages = [
".",
"common",
"common/hexutil",
"common/math",
"core/types",
"crypto",
"crypto/secp256k1",
"crypto/sha3",
"ethclient",
"ethdb",
"log",
"metrics",
"p2p/netutil",
"params",
"rlp",
"rpc",
"trie",
]
pruneopts = ""
revision = "89451f7c382ad2185987ee369f16416f89c28a7d"
version = "v1.8.15"
[[projects]]
digest = "1:9ca737b471693542351e112c9e86be9bf7385e42256893a09ecb2a98e2036f74"
name = "github.com/go-stack/stack"
packages = ["."]
pruneopts = ""
revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc"
version = "v1.7.0"
[[projects]]
digest = "1:61416415ed09917c36481eb30d3d5836c7b10e3225f412546a1f7a80fc5b33ce"
name = "github.com/gobuffalo/packr"
packages = ["."]
pruneopts = ""
revision = "5a2cbb54c4e7d482e3f518c56f1f86f133d5204f"
version = "v1.13.7"
[[projects]]
digest = "1:0a3f6a0c68ab8f3d455f8892295503b179e571b7fefe47cc6c556405d1f83411"
name = "github.com/gogo/protobuf"
packages = ["proto"]
pruneopts = ""
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:107b233e45174dbab5b1324201d092ea9448e58243ab9f039e4c0f332e121e3a"
name = "github.com/golang/glog"
packages = ["."]
pruneopts = ""
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
[[projects]]
digest = "1:bcb38c8fc9b21bb8682ce2d605a7d4aeb618abc7f827e3ac0b27c0371fdb23fb"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = ""
revision = "925541529c1fa6821df4e44ce2723319eb2be768"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:09307dfb1aa3f49a2bf869dcfa4c6c06ecd3c207221bd1c1a1141f0e51f209eb"
name = "github.com/golang/snappy"
packages = ["."]
pruneopts = ""
revision = "553a641470496b2327abcac10b36396bd98e45c9"
[[projects]]
digest = "1:64d212c703a2b94054be0ce470303286b177ad260b2f89a307e3d1bb6c073ef6"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = ""
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:f52c08004f0c94b201138a846bdc0162ed8860a569cb57f2956315daaa27d8a3"
name = "github.com/jakm/bchutil"
packages = ["."]
pruneopts = ""
revision = "5a273ca8a96628732c07ff5cfb9f3e7d965241e8"
[[projects]]
branch = "master"
digest = "1:b5544974001cf7d5290cdb9e74ed939dcb3d7f52d4f618d664e0135dda5fa87c"
name = "github.com/jakm/btcutil"
packages = [".","base58","bech32","chaincfg","txscript"]
packages = [
".",
"base58",
"bech32",
"chaincfg",
"txscript",
]
pruneopts = ""
revision = "224b76333062172edefdeb502123fdda12205f76"
[[projects]]
branch = "master"
digest = "1:b38a66184fb38b517900ab365f43557ea7e4efe36f939e2fcb53ec0aa92b29c5"
name = "github.com/juju/errors"
packages = ["."]
pruneopts = ""
revision = "c7d06af17c68cd34c835053720b21f6549d9b0ee"
[[projects]]
branch = "master"
digest = "1:538b60b5e6074d45962fa3dc0bfe721c303f5b31be99e809653380a67afcc289"
name = "github.com/martinboehm/golang-socketio"
packages = [".","protocol","transport"]
packages = [
".",
"protocol",
"transport",
]
pruneopts = ""
revision = "f60b0a8befde091474a624a8ffd81ee9912957b3"
[[projects]]
digest = "1:4c23ced97a470b17d9ffd788310502a077b9c1f60221a85563e49696276b4147"
name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"]
pruneopts = ""
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:4b0d251e61fe112ebeb52ce2162decdf13ae4a031c6e598c552a9b349dc4c74d"
name = "github.com/mr-tron/base58"
packages = ["base58"]
pruneopts = ""
revision = "c1bdf7c52f59d6685ca597b9955a443ff95eeee6"
[[projects]]
branch = "master"
digest = "1:d2df7451f4829b4dd6422e1ebf336fe9400220efe735f80f27d84a07e3180a1f"
name = "github.com/pebbe/zmq4"
packages = ["."]
pruneopts = ""
revision = "5b443b6471cea4b4f9f85025530c04c93233f76a"
[[projects]]
digest = "1:7365acd48986e205ccb8652cc746f09c8b7876030d53710ea6ef7d0bd0dcd7ca"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = ""
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
digest = "1:4142d94383572e74b42352273652c62afec5b23f325222ed09198f46009022d1"
name = "github.com/prometheus/client_golang"
packages = ["prometheus","prometheus/promhttp"]
packages = [
"prometheus",
"prometheus/promhttp",
]
pruneopts = ""
revision = "c5b7fccd204277076155f10851dad72b76a49317"
version = "v0.8.0"
[[projects]]
branch = "master"
digest = "1:60aca47f4eeeb972f1b9da7e7db51dee15ff6c59f7b401c1588b8e6771ba15ef"
name = "github.com/prometheus/client_model"
packages = ["go"]
pruneopts = ""
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
[[projects]]
branch = "master"
digest = "1:af21ee3e0a8212f17bb317cd7237f9920bcb2641a291ac111f30f63b3cab817f"
name = "github.com/prometheus/common"
packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"]
packages = [
"expfmt",
"internal/bitbucket.org/ww/goautoneg",
"model",
]
pruneopts = ""
revision = "d0f7cd64bda49e08b22ae8a730aa57aa0db125d6"
[[projects]]
branch = "master"
digest = "1:61df0898746840afc7be5dc2c3eeec83022fab70df11ecee5b16c85e912cf5ed"
name = "github.com/prometheus/procfs"
packages = [".","internal/util","nfs","xfs"]
packages = [
".",
"internal/util",
"nfs",
"xfs",
]
pruneopts = ""
revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e"
[[projects]]
digest = "1:fe0d7d3a09f5f5ee86ac94afb59c4ef39b08580417732aee805b3d91a90370e7"
name = "github.com/rs/cors"
packages = ["."]
pruneopts = ""
revision = "feef513b9575b32f84bafa580aad89b011259019"
version = "v1.3.0"
[[projects]]
digest = "1:94e86732ddbefd10e7f570b1c850b47cd69500ddeb58d3e4c77f40683dfa6bbe"
name = "github.com/schancel/cashaddr-converter"
packages = ["address","baseconv","cashaddress","legacy"]
packages = [
"address",
"baseconv",
"cashaddress",
"legacy",
]
pruneopts = ""
revision = "0a38f5822f795dc3727b4caacc298e02938d9eb1"
version = "v9"
[[projects]]
branch = "master"
digest = "1:175bc8d87d54849b9b9fc6cd473c5830e090fbf3c2f0ca71c7642a697e5d9237"
name = "github.com/syndtr/goleveldb"
packages = ["leveldb","leveldb/cache","leveldb/comparer","leveldb/errors","leveldb/filter","leveldb/iterator","leveldb/journal","leveldb/memdb","leveldb/opt","leveldb/storage","leveldb/table","leveldb/util"]
packages = [
"leveldb",
"leveldb/cache",
"leveldb/comparer",
"leveldb/errors",
"leveldb/filter",
"leveldb/iterator",
"leveldb/journal",
"leveldb/memdb",
"leveldb/opt",
"leveldb/storage",
"leveldb/table",
"leveldb/util",
]
pruneopts = ""
revision = "714f901b98fdb3aa954b4193d8cbd64a28d80cad"
[[projects]]
branch = "master"
digest = "1:406915e133a786c711bbff085eb9c20f8c50b01ddae6e9f3eb00557bc080b153"
name = "github.com/tecbot/gorocksdb"
packages = ["."]
pruneopts = ""
revision = "214b6b7bc0f06812ab5602fdc502a3e619916f38"
[[projects]]
branch = "master"
digest = "1:47ff8b3229cff95d3cf3738c7a8461fdeacd3f46801e54d301a62500605ce202"
name = "golang.org/x/crypto"
packages = ["ripemd160"]
pruneopts = ""
revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
[[projects]]
branch = "master"
digest = "1:40dd5a4f1e82c4d3dc3de550a96152f6a8937bcfcb20c7ee34685f8764e1bda5"
name = "golang.org/x/net"
packages = ["websocket"]
pruneopts = ""
revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41"
[[projects]]
branch = "v2"
digest = "1:a585c075875ab9c344f7840a927f09f3285563f7318e761a1d61d642316f2217"
name = "gopkg.in/karalabe/cookiejar.v2"
packages = ["collections/prque"]
pruneopts = ""
revision = "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57"
[[projects]]
branch = "v2"
digest = "1:4f830ee018eb8c56d0def653ad7c9a1d2a053f0cef2ac6b2200f73b98fa6a681"
name = "gopkg.in/natefinch/npipe.v2"
packages = ["."]
pruneopts = ""
revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "3a7b863bec3806ba9460f3961e2d6e8ff4b77e5f66d196b1f79bd37fa6bf8d82"
input-imports = [
"github.com/bsm/go-vlq",
"github.com/btcsuite/btcd/blockchain",
"github.com/btcsuite/btcd/chaincfg/chainhash",
"github.com/btcsuite/btcd/wire",
"github.com/deckarep/golang-set",
"github.com/ethereum/go-ethereum",
"github.com/ethereum/go-ethereum/common",
"github.com/ethereum/go-ethereum/common/hexutil",
"github.com/ethereum/go-ethereum/core/types",
"github.com/ethereum/go-ethereum/ethclient",
"github.com/ethereum/go-ethereum/rpc",
"github.com/gobuffalo/packr",
"github.com/gogo/protobuf/proto",
"github.com/golang/glog",
"github.com/golang/protobuf/proto",
"github.com/gorilla/websocket",
"github.com/jakm/bchutil",
"github.com/jakm/btcutil",
"github.com/jakm/btcutil/base58",
"github.com/jakm/btcutil/chaincfg",
"github.com/jakm/btcutil/txscript",
"github.com/juju/errors",
"github.com/martinboehm/golang-socketio",
"github.com/martinboehm/golang-socketio/transport",
"github.com/pebbe/zmq4",
"github.com/prometheus/client_golang/prometheus",
"github.com/prometheus/client_golang/prometheus/promhttp",
"github.com/schancel/cashaddr-converter/address",
"github.com/tecbot/gorocksdb",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -9,7 +9,8 @@ import (
"blockbook/bchain/coins/digibyte"
"blockbook/bchain/coins/dogecoin"
"blockbook/bchain/coins/eth"
"blockbook/bchain/coins/fujicoin"
"blockbook/bchain/coins/flo"
"blockbook/bchain/coins/fujicoin"
"blockbook/bchain/coins/gamecredits"
"blockbook/bchain/coins/grs"
"blockbook/bchain/coins/litecoin"
@ -61,6 +62,7 @@ func init() {
BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC
BlockChainFactories["Groestlcoin Testnet"] = grs.NewGroestlcoinRPC
BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC
BlockChainFactories["Flo"] = flo.NewFloRPC
}
// GetCoinNameFromConfig gets coin name and coin shortcut from config file

View File

@ -0,0 +1,63 @@
package flo
import (
"blockbook/bchain/coins/btc"
"github.com/btcsuite/btcd/wire"
"github.com/jakm/btcutil/chaincfg"
)
const (
MainnetMagic wire.BitcoinNet = 0xf1a5c0fd
TestnetMagic wire.BitcoinNet = 0xf25ac0fd
RegtestMagic wire.BitcoinNet = 0xdab5bffa
)
var (
MainNetParams chaincfg.Params
TestNetParams chaincfg.Params
)
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
MainNetParams.PubKeyHashAddrID = []byte{35}
MainNetParams.ScriptHashAddrID = []byte{94}
MainNetParams.Bech32HRPSegwit = "flo"
TestNetParams = chaincfg.TestNet3Params
TestNetParams.Net = TestnetMagic
TestNetParams.PubKeyHashAddrID = []byte{115}
TestNetParams.ScriptHashAddrID = []byte{198}
TestNetParams.Bech32HRPSegwit = "tflo"
}
// FloParser handle
type FloParser struct {
*btc.BitcoinParser
}
// NewFloParser returns new FloParser instance
func NewFloParser(params *chaincfg.Params, c *btc.Configuration) *FloParser {
return &FloParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
}
// GetChainParams contains network parameters for the main Flo network,
// and the test Flo 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
}
}

View File

@ -0,0 +1,288 @@
// +build unittest
package flo
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress_Testnet(t *testing.T) {
type args struct {
address string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "P2PKH1",
args: args{address: "mgPdTgEq6YqUJ4yzQgR8jH5TCX5c5yRwCP"},
want: "76a91409957dfdb3eb620a94b99857e13949551584c33688ac",
wantErr: false,
},
{
name: "P2SH1-legacy",
args: args{address: "2MvGVySztevmycxrSmMRjJaVj2iJin7qpap"},
want: "a9142126232e3f47ae0f1246ec5f05fc400d83c86a0d87",
wantErr: false,
},
{
name: "P2SH2-legacy",
args: args{address: "2N9a2TNzWz1FEKGFxUdMEh62V83URdZ5QAZ"},
want: "a914b31049e7ee51501fe19e3e0cdb803dc84cf99f9e87",
wantErr: false,
},
{
name: "P2SH1",
args: args{address: "QPdG6Ts8g2q4m9cVPTTkPGwAB6kYgXB7Hc"},
want: "a9142126232e3f47ae0f1246ec5f05fc400d83c86a0d87",
wantErr: false,
},
{
name: "P2SH2",
args: args{address: "QcvnaPrm17JKTT216jPFmnTvGRvFX2fWzN"},
want: "a914b31049e7ee51501fe19e3e0cdb803dc84cf99f9e87",
wantErr: false,
},
}
parser := NewLitecoinParser(GetChainParams("test"), &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_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: "LgJGe7aKy1wfXESKhiKeRWj6z4KjzCfXNW"},
want: "76a914e72ba56ab6afccac045d696b979e3b5077e88d1988ac",
wantErr: false,
},
{
name: "P2PKH2",
args: args{address: "LiTVReQ6N8rWc2pNg2XMwCWq7A9P15teWg"},
want: "76a914feda50542e61108cf53b93dbffa0959f91ccb32588ac",
wantErr: false,
},
{
name: "P2SH1",
args: args{address: "MLTQ8niHMnpJLNvK72zBeY91hQmUtoo8nX"},
want: "a91489ba6cf45546f91f1bdf553e695d63fc6b8795bd87",
wantErr: false,
},
{
name: "P2SH2",
args: args{address: "MAVWzxXm8KGkZTesqLtqywzrvbs96FEoKy"},
want: "a9141c6fbaf46d64221e80cbae182c33ddf81b9294ac87",
wantErr: false,
},
{
name: "witness_v0_keyhash",
args: args{address: "ltc1q5fgkuac9s2ry56jka5s6zqsyfcugcchrqgz2yl"},
want: "0014a2516e770582864a6a56ed21a102044e388c62e3",
wantErr: false,
},
{
name: "witness_v0_scripthashx",
args: args{address: "ltc1qu9dgdg330r6r84g5mw7wqshg04exv2uttmw2elfwx74h5tgntuzsk3x5nd"},
want: "0020e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05",
wantErr: false,
},
}
parser := NewFloParser(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)
}
})
}
}
var (
testTx1 bchain.Tx
testTxPacked1 = "0001e4538ba8d7aa2002000000031e1977dc524bec5929e95d8d0946812944b7b5bda12f5b99fdf557773f2ee65e0100000000ffffffff8a398e44546dce0245452b90130e86832b21fd68f26662bc33aeb7c6c115d23c1900000000ffffffffb807ab93a7fcdff7af6d24581a4a18aa7c1db1ebecba2617a6805b009513940f0c00000000ffffffff020001a04a000000001976a9141ae882e788091732da6910595314447c9e38bd8d88ac27440f00000000001976a9146b474cbf0f6004329b630bdd4798f2c23d1751b688ac00000000"
)
func init() {
testTx1 = bchain.Tx{
Hex: "02000000031e1977dc524bec5929e95d8d0946812944b7b5bda12f5b99fdf557773f2ee65e0100000000ffffffff8a398e44546dce0245452b90130e86832b21fd68f26662bc33aeb7c6c115d23c1900000000ffffffffb807ab93a7fcdff7af6d24581a4a18aa7c1db1ebecba2617a6805b009513940f0c00000000ffffffff020001a04a000000001976a9141ae882e788091732da6910595314447c9e38bd8d88ac27440f00000000001976a9146b474cbf0f6004329b630bdd4798f2c23d1751b688ac00000000",
Blocktime: 1519053456,
Txid: "1c50c1770374d7de2f81a87463a5225bb620d25fd467536223a5b715a47c9e32",
LockTime: 0,
Version: 2,
Vin: []bchain.Vin{
{
ScriptSig: bchain.ScriptSig{
Hex: "",
},
Txid: "5ee62e3f7757f5fd995b2fa1bdb5b744298146098d5de92959ec4b52dc77191e",
Vout: 1,
Sequence: 4294967295,
},
{
ScriptSig: bchain.ScriptSig{
Hex: "",
},
Txid: "3cd215c1c6b7ae33bc6266f268fd212b83860e13902b454502ce6d54448e398a",
Vout: 25,
Sequence: 4294967295,
},
{
ScriptSig: bchain.ScriptSig{
Hex: "",
},
Txid: "0f941395005b80a61726baecebb11d7caa184a1a58246daff7dffca793ab07b8",
Vout: 12,
Sequence: 4294967295,
},
},
Vout: []bchain.Vout{
{
ValueSat: *big.NewInt(1252000000),
N: 0,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a9141ae882e788091732da6910595314447c9e38bd8d88ac",
Addresses: []string{
"LMgENNXzzuPxp7vfMjDrCU44bsmrEMgqvc",
},
},
},
{
ValueSat: *big.NewInt(1000487),
N: 1,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a9146b474cbf0f6004329b630bdd4798f2c23d1751b688ac",
Addresses: []string{
"LV1ByjbJNFTHyFQqwqwdJXKJznYDzXzg4B",
},
},
},
},
}
}
func Test_PackTx(t *testing.T) {
type args struct {
tx bchain.Tx
height uint32
blockTime int64
parser *FloParser
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "flo-1",
args: args{
tx: testTx1,
height: 123987,
blockTime: 1519053456,
parser: NewFloParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTxPacked1,
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 *FloParser
}
tests := []struct {
name string
args args
want *bchain.Tx
want1 uint32
wantErr bool
}{
{
name: "flo-1",
args: args{
packedTx: testTxPacked1,
parser: NewFloParser(GetChainParams("main"), &btc.Configuration{}),
},
want: &testTx1,
want1: 123987,
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)
}
})
}
}

View File

@ -0,0 +1,57 @@
package flo
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
)
// FloRPC is an interface to JSON-RPC flod service.
type FloRPC struct {
*btc.BitcoinRPC
}
// NewFloRPC returns new FloRPC instance.
func NewFloRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
b, err := btc.NewBitcoinRPC(config, pushHandler)
if err != nil {
return nil, err
}
s := &FloRPC{
b.(*btc.BitcoinRPC),
}
s.RPCMarshaler = btc.JSONMarshalerV2{}
s.ChainConfig.SupportsEstimateFee = false
return s, nil
}
// Initialize initializes FloRPC instance.
func (b *FloRPC) 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 = NewFloParser(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
}

65
configs/coins/flo.json Normal file
View File

@ -0,0 +1,65 @@
{
"coin": {
"name": "Flo",
"shortcut": "FLO",
"label": "Flo",
"alias": "flo"
},
"ports": {
"backend_rpc": 8066,
"backend_message_queue": 38366,
"blockbook_internal": 9066,
"blockbook_public": 9166
},
"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-flo",
"package_revision": "satoshilabs-1",
"system_user": "flo",
"version": "0.15.1.1",
"binary_url": "https://github.com/floblockchain/flo/releases/download/v0.15.1.1/flo-0.15.1-x86_64-linux-gnu.tar.gz",
"verification_type": "sha256",
"verification_source": "40a725947d00ee4af519d9166b824cf2bfe1a144bf4a14004d756ece5063bf8d",
"extract_command": "tar -C backend --strip 1 -xf",
"exclude_files": [
"bin/flo-qt"
],
"exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/flod -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,
"server_config_file": "bitcoin_like.conf",
"client_config_file": "bitcoin_like_client.conf",
"additional_params": {
"deprecatedrpc": "estimatefee"
}
},
"blockbook": {
"package_name": "blockbook-flo",
"system_user": "blockbook-flo",
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
"explorer_url": "",
"additional_params": "-dbcache=1073741824",
"block_chain": {
"parse": true,
"mempool_workers": 8,
"mempool_sub_workers": 2,
"block_addresses_to_keep": 300,
"additional_params": {}
}
},
"meta": {
"package_maintainer": "bitspill",
"package_maintainer_email": "blockbook@bitspill.net"
}
}

View File

@ -20,6 +20,7 @@
| Groestlcoin | 9045 | 9145 | 8045 | 38345 |
| Bitcoin Cash SV | 9046 | 9146 | 8046 | 38346 |
| Fujicoin | 9048 | 9148 | 8048 | 38348 |
| Flo | 9066 | 9166 | 8066 | 38366 |
| Bitcoin Testnet | 19030 | 19130 | 18030 | 48330 |
| Bitcoin Cash Testnet | 19031 | 19131 | 18031 | 48331 |
| Zcash Testnet | 19032 | 19132 | 18032 | 48332 |