Skip to content

Commit

Permalink
增加BTC协议,还未完成交易的同步
Browse files Browse the repository at this point in the history
  • Loading branch information
lmxdawn committed Apr 24, 2022
1 parent f92f72e commit 5c4b3f6
Show file tree
Hide file tree
Showing 15 changed files with 915 additions and 136 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,14 @@ $ wallet -c config.yml

| 参数名 | 描述 |
| ---- | ---- |
| coin_name | 合约地址(为空表示主币) |
| contract | 合约类型(波场需要区分是TRC20还是TRC10) |
| contract_type | 协议名称 |
| protocol | 币种名称 |
| coin_name | 币种名称 |
| contract | 合约地址(为空表示主币) |
| contract_type | 合约类型(波场需要区分是TRC20还是TRC10) |
| protocol | 协议名称 |
| network | 网络名称(暂时BTC协议有用{MainNet:主网,TestNet:测试网,TestNet3:测试网3,SimNet:测试网}) |
| rpc | rpc配置 |
| user | rpc用户名(没有则为空) |
| pass | rpc密码(没有则为空) |
| file | db文件路径配置 |
| wallet_prefix | 钱包的存储前缀 |
| hash_prefix | 交易哈希的存储前缀 |
Expand Down
73 changes: 73 additions & 0 deletions btc/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package btc

import (
"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
)

type Client struct {
rpc *rpcclient.Client
}

func NewClient(host, user, pass string) (*Client, error) {
client, err := rpcclient.New(&rpcclient.ConnConfig{
HTTPPostMode: true,
DisableTLS: true,
Host: host,
User: user,
Pass: pass,
}, nil)

if err != nil {
return nil, err
}

return &Client{
rpc: client,
}, nil
}

// GetBlockCount 获取区块数量,调用返回本地最优链中的区块数量。
func (c *Client) GetBlockCount() (int64, error) {
return c.rpc.GetBlockCount()
}

// GetBlockHash 获取指定高度区块的哈希。
func (c *Client) GetBlockHash(blockNumber int64) (*chainhash.Hash, error) {
return c.rpc.GetBlockHash(blockNumber)
}

// ImportAddress 导入地址
func (c *Client) ImportAddress(address string) error {
return c.rpc.ImportAddress(address)
}

// ListUnspent 获取未交易的UTX
func (c *Client) ListUnspent(address btcutil.Address) (listUnSpent []btcjson.ListUnspentResult, err error) {
adds := [1]btcutil.Address{address}
listUnSpent, err = c.rpc.ListUnspentMinMaxAddresses(1, 999999, adds[:])
if err != nil {
return
}
return
}

// SendRawTransaction 发送裸交易
func (c *Client) SendRawTransaction(tx *wire.MsgTx) (*chainhash.Hash, error) {

return c.rpc.SendRawTransaction(tx, false)

}

// ListSinceBlock 查询指定区块后发生的钱包交易
func (c *Client) ListSinceBlock(blockHash *chainhash.Hash) (*btcjson.ListSinceBlockResult, error) {
return c.rpc.ListSinceBlock(blockHash)
}

// ListTransactions 查询最近发生的钱包交易
func (c *Client) ListTransactions(account string) ([]btcjson.ListTransactionsResult, error) {
return c.rpc.ListTransactions(account)
}
142 changes: 142 additions & 0 deletions btc/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package btc

import (
"fmt"
"github.com/btcsuite/btcutil"
"testing"
)

func TestClient_ListUnspent(t *testing.T) {

var (
//host = "47.243.189.44:30000"
//user = "BTCuser"
//pass = "BTCpassword"
//network = "MainNet"

host = "127.0.0.1:18332"
user = "admin"
pass = "123456"
network = "TestNet3"
defaultNet = getNetwork(network)
)
//address := "2N8Ah8xiqrfb37aktkkwYmMqpDGQJMSDAWY"
address := "2NGU5d9Y3uKLJXZa6GgYm2bf4wNK33GcAwJ"
client, err := NewClient(host, user, pass)
if err != nil {
t.Error("创建client失败:", err)
}
fromAddress, err := btcutil.DecodeAddress(address, defaultNet)
if err != nil {
t.Error("地址错误:", err)
}

list, err := client.ListUnspent(fromAddress)
if err != nil {
t.Error("获取未交易的UTXO失败:", err)
}

fmt.Println(list)

}

func TestClient_GetBlockHash(t *testing.T) {

var (
host = "127.0.0.1:18332"
user = "admin"
pass = "123456"
)
client, err := NewClient(host, user, pass)
if err != nil {
t.Error("创建client失败:", err)
}

blockNumber := int64(2000000)
hash, err := client.GetBlockHash(blockNumber)
if err != nil {
t.Error("获取区块哈希失败:", err)
}

fmt.Println(hash)

}

func TestClient_ListSinceBlock(t *testing.T) {

var (
//host = "47.243.189.44:30000"
//user = "BTCuser"
//pass = "BTCpassword"

host = "127.0.0.1:18332"
user = "admin"
pass = "123456"
)
client, err := NewClient(host, user, pass)
if err != nil {
t.Error("创建client失败:", err)
}

blockNumber := int64(600000)
hash, err := client.GetBlockHash(blockNumber)
if err != nil {
t.Error("获取区块哈希失败:", err)
}

fmt.Println(hash)

list, err := client.ListSinceBlock(hash)
if err != nil {
t.Error("获取交易列表失败:", err)
}

fmt.Println(list)

}

func TestClient_ListTransactions(t *testing.T) {

var (
//host = "47.243.189.44:30000"
//user = "BTCuser"
//pass = "BTCpassword"
host = "127.0.0.1:18332"
user = "admin"
pass = "123456"
)
client, err := NewClient(host, user, pass)
if err != nil {
t.Error("创建client失败:", err)
}

address := "2N8Ah8xiqrfb37aktkkwYmMqpDGQJMSDAWY"
list, err := client.ListTransactions(address)
if err != nil {
t.Error("获取最近发生的钱包交易失败:", err)
}

fmt.Println(list)

}

func TestClient_ImportAddress(t *testing.T) {

var (
host = "127.0.0.1:18332"
user = "admin"
pass = "123456"
)
client, err := NewClient(host, user, pass)
if err != nil {
t.Error("创建client失败:", err)
}

//address := "2N8Ah8xiqrfb37aktkkwYmMqpDGQJMSDAWY"
address := "2NGU5d9Y3uKLJXZa6GgYm2bf4wNK33GcAwJ"
err = client.ImportAddress(address)
if err != nil {
t.Error("导入地址失败:", err)
}

}
23 changes: 23 additions & 0 deletions btc/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package btc

import (
"github.com/btcsuite/btcd/chaincfg"
"strings"
)

func getNetwork(network string) *chaincfg.Params {
var defaultNet *chaincfg.Params

//指定网络 {MainNet:主网,TestNet:测试网,TestNet3:测试网3,SimNet:测试网}
switch strings.ToLower(network) {
case "mainnet":
defaultNet = &chaincfg.MainNetParams
case "testnet":
defaultNet = &chaincfg.RegressionNetParams
case "testnet3":
defaultNet = &chaincfg.TestNet3Params
case "simnet":
defaultNet = &chaincfg.SimNetParams
}
return defaultNet
}
82 changes: 82 additions & 0 deletions btc/wallet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package btc

import (
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcutil"
)

type Wallet struct {
LegacyAddress string // (P2PKH)格式,普通非隔离验证地址(由1开头)| 普及度:较高 | 矿工费:较低
NestedSegWitAddress string // (P2SH)格式,隔离验证(兼容)地址(由3开头)| 普及度:较高 | 矿工费:较低
NativeSegWitAddress string // (Bech32)格式,隔离验证(原生)地址(由bc1开头)| 普及度:较低 | 矿工费:最低
PublicKey string
PrivateKey string
}

// CreateWallet 创建钱包
func CreateWallet(defaultNet *chaincfg.Params) (*Wallet, error) {

//1.生成私钥,参数:Secp256k1
privateKey, err := btcec.NewPrivateKey(btcec.S256())
if err != nil {
return nil, err
}

//2.转成wif格式
privateKeyWif, err := btcutil.NewWIF(privateKey, defaultNet, true)
if err != nil {
return nil, err
}

return getWalletByPrivateKey(defaultNet, privateKeyWif)

}

// GetWalletByPrivateKey 获取钱包通过私钥,返回地址和公钥
func GetWalletByPrivateKey(defaultNet *chaincfg.Params, privateKeyStr string) (*Wallet, error) {

// 转成wif格式
privateKeyWif, err := btcutil.DecodeWIF(privateKeyStr)
if err != nil {
return nil, err
}

return getWalletByPrivateKey(defaultNet, privateKeyWif)
}

// getWalletByPrivateKey 根据网络和 私钥的 wif 获取地址
func getWalletByPrivateKey(defaultNet *chaincfg.Params, wif *btcutil.WIF) (*Wallet, error) {

// 获取publicKey
publicKeySerial := wif.PrivKey.PubKey().SerializeCompressed()

publicKey, err := btcutil.NewAddressPubKey(publicKeySerial, defaultNet)
if err != nil {
return nil, err
}

pkHash := btcutil.Hash160(publicKeySerial)
nativeSegWitAddressHash, err := btcutil.NewAddressWitnessPubKeyHash(pkHash, defaultNet)
if err != nil {
return nil, err
}

nestedSegWitAddressWitnessProg, err := txscript.PayToAddrScript(nativeSegWitAddressHash)
if err != nil {
return nil, err
}
nestedSegWitAddressHash, err := btcutil.NewAddressScriptHash(nestedSegWitAddressWitnessProg, defaultNet)
if err != nil {
return nil, err
}

return &Wallet{
LegacyAddress: publicKey.EncodeAddress(),
NestedSegWitAddress: nestedSegWitAddressHash.EncodeAddress(),
NativeSegWitAddress: nativeSegWitAddressHash.EncodeAddress(),
PublicKey: publicKey.String(),
PrivateKey: wif.String(),
}, nil
}
Loading

0 comments on commit 5c4b3f6

Please sign in to comment.