Go 实现比特币多重签名服务

作者:老码农不上班 链接:https://www.jianshu.com/p/21107f737b98 來源:简书

使用 Go 写了个比特币多重签名的服务,这篇文章总结服务的结构及实现思路。

源码中主要涉及到的 Go package :

  • dep Go package 管理工具
  • cobra 实现 cli
  • LevelDB 保存加密处理后的私钥
  • gin 实现接口接受外部服务请求
  • gRPC & protocol buffer 内部服务调用
  • btcd 连接比特币节点的 JSON-RPC 比特币区块、交易数据结构工具

采用 3-3 多重签名(在这里硬编码了,最好的做法是让用户动态选择 x-y 签名),也就是三个普通地址生成多签地址,消费多签地址中的比特币需要三个地址对应的私钥成功签名才可构建交易的数据结构,签名服务通过 gRPC 获取普通地址私钥进行签名,最后把签名的数据通过节点广播到比特币网络。

 1// serveCmd represents the api command
 2var serveCmd = &cobra.Command{
 3    Use:   "api",
 4    Short: "External API",
 5    Long:  `Provide WEB API for external`,
 6    Run: func(cmd *cobra.Command, args []string) {
 7        ormDB = ormBbAlias{dbConn()}
 8        ormDB.DBMigrate()
 9        defer ormDB.Close()
10        switch api {
11        case "normal_address":
12            normalAddress()
13        case "multisig_address":
14            multisigAddress()
15        case "sign_tx":
16            signTx()
17        case "grpc":
18            addressServer()
19        default:
20            log.Fatalf("You must specify -a flag")
21        }
22    },
23}

启动服务命令:

 1➜  bitcoin_multisig_with_node git:(master) ✗ bitcoin_multisig_with_node api -h
 2Using Configure file: /Users/hww/bitcoin.yml
 3Provide WEB API for external
 4
 5Usage:
 6  bitcoin_multisig_with_node api [flags]
 7
 8Flags:
 9  -a, --api string   External API(value: normal_address, multisig_address sign_tx grpc)
10  -h, --help         help for api

生成普通地址

在三台独立的内网服务器部署生成普通地址的服务,确保私钥不集中存储在一台服务器。当然在本地开发时,我们可以开启不同的端口启动服务给外部请求生成普通地址:

 1var (
 2    client bitcoinClientAlias
 3    g      errgroup.Group
 4)
 5
 6func mormalRoute() http.Handler {
 7    r := ginEngine()
 8    r.Use(location.Default())
 9    r.GET("/address", normolAddressHandler)
10    return r
11}
12
13func normalAddress() {
14    server00 := &http.Server{
15        Addr:         ":3000",
16        Handler:      mormalRoute(),
17        ReadTimeout:  5 * time.Second,
18        WriteTimeout: 10 * time.Second,
19    }
20
21    server01 := &http.Server{
22        Addr:         ":3001",
23        Handler:      mormalRoute(),
24        ReadTimeout:  5 * time.Second,
25        WriteTimeout: 10 * time.Second,
26    }
27
28    server02 := &http.Server{
29        Addr:         ":3002",
30        Handler:      mormalRoute(),
31        ReadTimeout:  5 * time.Second,
32        WriteTimeout: 10 * time.Second,
33    }
34
35    g.Go(func() error {
36        return server00.ListenAndServe()
37    })
38
39    g.Go(func() error {
40        return server01.ListenAndServe()
41    })
42
43    g.Go(func() error {
44        return server02.ListenAndServe()
45    })
46
47    if err := g.Wait(); err != nil {
48        log.Fatal(err)
49    }
50}
51
52func normolAddressHandler(c *gin.Context) {
53    address, pubkey, err := generateNormalAddress("regtest")
54    if err != nil {
55        ginResponseException(c, 400, err)
56        return
57    }
58
59    ormDB.Create(&AddressPub{Address: *address, PublicKeyBytes: *pubkey, URL: location.Get(c).Hostname()})
60
61    c.JSON(200, gin.H{
62        "status":  200,
63        "address": address,
64    })
65}

生成多签地址

生成多签地址服务当初部署,你也可以通过实现比特币多签地址生成协议脱离节点生成多钱地址,在这里我们提供一个对外的接口,用户把三个普通地址传给 web 服务,服务端处理请求并返回多签地址。

 1func multisigAddress() {
 2    c := config.bitcoinClient()
 3    client = bitcoinClientAlias{c}
 4
 5    r := ginEngine()
 6    r.GET("/address", multisigAddressHandle)
 7    if err := r.Run(":3003"); err != nil {
 8        log.Fatalf(err.Error())
 9    }
10}

构建交易并首次签名

签名服务单独部署,通过 gRPC 去部署生成普通地址的服务获取私钥进行签名。

 1func signTx() {
 2    c := config.bitcoinClient()
 3    client = bitcoinClientAlias{c}
 4    r := ginEngine()
 5    r.GET("/issue", issueTx)
 6    r.GET("/confirm", confirmHandle)
 7    if err := r.Run(":3004"); err != nil {
 8        log.Fatalf(err.Error())
 9    }
10
11}

开启 gRPC 服务端服务,接收签名服务发来的获取私钥请求

 1func addressServer() {
 2    lis, err := net.Listen("tcp", port)
 3    if err != nil {
 4        log.Fatalf("failed to listen: %v", err)
 5    }
 6
 7    s := grpc.NewServer()
 8    RegisterNormalAddressServer(s, &gRPCServer{})
 9
10    reflection.Register(s)
11    if err := s.Serve(lis); err != nil {
12        log.Fatalf("failed to gRPC serve: %v", err)
13    }
14}

构建交易并首次签名

 1func issueTx(c *gin.Context) {
 2    var (
 3        params     *txParams
 4        dbMultisig MultiSig
 5        dbAddress  AddressPub
 6        inputs     []btcjson.RawTxInput
 7    )
 8
 9    // 参数校验
10    params = new(txParams) // should initialize pointer before use
11    txidsHash, err := params.signTxParams(c)
12    if err != nil {
13        ginResponseException(c, 400, err)
14        return
15    }
16
17    ormDB.Where("address = ?", params.From).First(&dbAddress)
18    ormDB.Model(&dbAddress).Related(&dbMultisig)
19
20    // 交易输入
21    txVins, err := client.constructVins(txidsHash)
22    if err != nil {
23        ginResponseException(c, 400, err)
24        return
25    }
26
27    // 构建多签交易
28    rawTx, err := client.NewMultiSigTx(dbMultisig, *params, txVins)
29    if err != nil {
30        ginResponseException(c, 400, err)
31        return
32    }
33
34    // 确认签名输入参数
35    for _, txRawResult := range txVins {
36        input := signInput(txRawResult, dbMultisig)
37        inputs = append(inputs, *input)
38    }
39
40    // gRPC 获取私钥
41    wif, err := dbAddress.grpcGetNormalAddressWif()
42    if err != nil {
43        ginResponseException(c, 400, err)
44        return
45    }
46
47    // 签名交易
48    msgTx, result, err := client.SignRawTransaction3(rawTx, inputs, []string{*wif})
49    if err != nil {
50        if err != nil {
51            ginResponseException(c, 400, err)
52            return
53        }
54    }
55
56    txHex := ""
57    if msgTx != nil {
58        // Serialize the transaction and convert to hex string.
59        buf := bytes.NewBuffer(make([]byte, 0, msgTx.SerializeSize()))
60        if err := msgTx.Serialize(buf); err != nil {
61            // return newFutureError(err)
62        }
63        txHex = hex.EncodeToString(buf.Bytes())
64    }
65
66    c.JSON(200, gin.H{
67        "status":  200,
68        "sign_tx": txHex,
69        "result":  result,
70    })
71}

最后一轮签名成功后使用 SendRawTransaction 广播交易到比特币网络

比特币 regtest 环境多重签名测试流程

首先具备比特币网络测试节点环境,详情可以 Bitcoin-core daemon and regtest install

生成地址

1// 请求不同机器生成普通地址
2curl "172.17.1.19:3000/address" // {"address":"1PnBXZzZTr7TLnr56ndBPLQANAGRAq9h4w","status":200}
3curl "172.17.1.19:3001/address" // {"address":"1KEPw2vC3NvGEcvguCt85uuKNmAGtYiuYC","status":200}
4curl "172.17.1.19:3002/address" // {"address":"1GKhpdfXHUC1mBM6WrD63tbKvMUyj9irdb","status":200}
5
6// 请求生成多签地址服务生成多签地址
7curl "172.17.1.9:3003/address?addresses=1PnBXZzZTr7TLnr56ndBPLQANAGRAq9h4w,1KEPw2vC3NvGEcvguCt85uuKNmAGtYiuYC,1GKhpdfXHUC1mBM6WrD63tbKvMUyj9irdb" //{"address":"2NBvbEGvFYiz3EAFyTsyUA8QKTmgBcJnbsb","status":200}

交易并首次签名

 1// 在 regtest 环境中给多签地址转入三笔交易生成三个 txid, 每笔 10 个币
 2bitcoin-cli -regtest sendtoaddress 2NBvbEGvFYiz3EAFyTsyUA8QKTmgBcJnbsb 10 // txid: 97adab60d7a0f71fca8f22b0007ef9b0b3f8eb1ce10341b4a5ee998d0bfbec72
 3bitcoin-cli -regtest sendtoaddress 2NBvbEGvFYiz3EAFyTsyUA8QKTmgBcJnbsb 10 // txid: 9244f24ec81630742591a15007e84d6e113db259340e5ac319e6d38440baf89f
 4bitcoin-cli -regtest sendtoaddress 2NBvbEGvFYiz3EAFyTsyUA8QKTmgBcJnbsb 10 // txid: 23a6466147c3d82fa2967dd3871b649793ee8b53f0463378ce7c0b8bcdf1278f
 5
 6// 开启挖矿确认以上三笔转账,以此我们的多签地址就有了 30 个比特币
 7bitcoin-cli -regtest generatetoaddress 10 2N8i6PbrW5nNtGbrHcPf5FJ1tNSyBou6t2b
 8/*
 9[
10  "3647fc9392ae2694b2ae6cc6336fad55f21fef4317e7b5bd13912a400d6ae84f",
11  "17acb72d5172d4d025bc3c7e953c7995d2b37fd6a50dac9dee705f3be2b83eb8",
12  "70a3c40665a20920bd25718ea80488e9dd8f9880d393a1b309b16be3cd84ddad",
13  "77abc300678788290a6ac054893c69877bbca6bb1c0010dae0afd578491dd67f",
14  "64d1087a723910a485989ffb15df7032617c06ae752f853af52868e08bcd4fe5",
15  "272f1761f1fcb6f8095775f200edf5e039f7dce36c166caa48f53fc821aafbf2",
16  "2740af50876e3b940b575455aecd014820b2515f15f126d6ef84ed384704c51f",
17  "050689882db8a2f55a3afb27a5083ddcc7951b93b379db165d8500785d0ccf2a",
18  "3c8b335bbcc7dc83fec5aa12e4ec2a881bd3067387b192806979bcd9c27ba18a",
19  "6cc259b0200d77c4a86255d3e19c02c47048c86933c2712fdbfae37cfd019f04"
20]
21*/
22
23// 在 regtest 环境中生成普通地址接收,用以接多签地址即将转出的币
24bitcoin-cli -regtest getnewaddress receiveaddress // 2Mu43Qw5pngjAmtu7n7evdkXE2E9ocXCft1
25
26// 生成多签地址的其中某个普通地址发起交易
27curl "192.168.7.44:3004/issue?txid=97adab60d7a0f71fca8f22b0007ef9b0b3f8eb1ce10341b4a5ee998d0bfbec72,9244f24ec81630742591a15007e84d6e113db259340e5ac319e6d38440baf89f,23a6466147c3d82fa2967dd3871b649793ee8b53f0463378ce7c0b8bcdf1278f&from=1KEPw2vC3NvGEcvguCt85uuKNmAGtYiuYC&to=2Mu43Qw5pngjAmtu7n7evdkXE2E9ocXCft1&amount=21"
28
29/*
30
31生成交易并返回首次签名结果
32{
33  "result":false,
34  "sign_tx":"020000000372ecfb0b8d99eea5b44103e11cebf8b3b0f97e00b0228fca1ff7a0d760abad9701000000fd150100483045022100b277e07d37f98f1c97dccf92f7c6bb7093622301d33bee48c57bb6fda687c068022066f1cafe7296fb57053577c1c3705b39dcfaa9f010c9699b20ad1cd98f0c5496014cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff9ff8ba4084d3e619c35a0e3459b23d116e4de80750a19125743016c84ef2449200000000fd14010047304402203062597d764932cd85ec9e5f82a6d471984d0d03ab1268ea4651343624387679022026203223c9a2968530f2af4a16bb079fee2905cc5cbba258f1f823603e57c895014cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff8f27f1cd8b0b7cce783346f0538bee9397641b87d37d96a22fd8c3476146a62301000000fd14010047304402206390095bade6a4159ad036d9cfe7e7f0004024da09d460784d8bb45806664e62022059d21c421e1ddcdb17d70998617af6fc85589b35f6bd7c423d5443da4ec48642014cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff0200752b7d0000000017a91413d2d93195352467f94a12a3def1e4c09d15ac278778d5a4350000000017a914cce437c88256ca0a9fa1eed83e5b192f4dcc39f18700000000",
35  "status":200
36}
37 */
38
39 // 第二个普通地址进行第二次签名
40 curl "192.168.7.44:3004/confirm?txid=97adab60d7a0f71fca8f22b0007ef9b0b3f8eb1ce10341b4a5ee998d0bfbec72,9244f24ec81630742591a15007e84d6e113db259340e5ac319e6d38440baf89f,23a6466147c3d82fa2967dd3871b649793ee8b53f0463378ce7c0b8bcdf1278f&from=1PnBXZzZTr7TLnr56ndBPLQANAGRAq9h4w&signtx=020000000372ecfb0b8d99eea5b44103e11cebf8b3b0f97e00b0228fca1ff7a0d760abad9701000000fd150100483045022100b277e07d37f98f1c97dccf92f7c6bb7093622301d33bee48c57bb6fda687c068022066f1cafe7296fb57053577c1c3705b39dcfaa9f010c9699b20ad1cd98f0c5496014cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff9ff8ba4084d3e619c35a0e3459b23d116e4de80750a19125743016c84ef2449200000000fd14010047304402203062597d764932cd85ec9e5f82a6d471984d0d03ab1268ea4651343624387679022026203223c9a2968530f2af4a16bb079fee2905cc5cbba258f1f823603e57c895014cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff8f27f1cd8b0b7cce783346f0538bee9397641b87d37d96a22fd8c3476146a62301000000fd14010047304402206390095bade6a4159ad036d9cfe7e7f0004024da09d460784d8bb45806664e62022059d21c421e1ddcdb17d70998617af6fc85589b35f6bd7c423d5443da4ec48642014cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff0200752b7d0000000017a91413d2d93195352467f94a12a3def1e4c09d15ac278778d5a4350000000017a914cce437c88256ca0a9fa1eed83e5b192f4dcc39f18700000000"
41
42/*
43{
44  "result":false,
45  "sign_tx":"020000000372ecfb0b8d99eea5b44103e11cebf8b3b0f97e00b0228fca1ff7a0d760abad9701000000fd5f01004830450221009c1518665cdb11e4e0d55e23fcbb19030c22ceaec081f646be0e8d062622df4c022037364e73584aee4fa9b8d26311039408f1d272b6e4955f0aaa377dc1090b87bb01483045022100b277e07d37f98f1c97dccf92f7c6bb7093622301d33bee48c57bb6fda687c068022066f1cafe7296fb57053577c1c3705b39dcfaa9f010c9699b20ad1cd98f0c549601004cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff9ff8ba4084d3e619c35a0e3459b23d116e4de80750a19125743016c84ef2449200000000fd5d0100473044022010ad85ee4f66b63c7765ccbdee57c66c9c37dee0965be4c5934e3e7f9b453e5102205089c146899a6228ba9acb12e714fb15f50619fccb99fe279d7aaa90489f39380147304402203062597d764932cd85ec9e5f82a6d471984d0d03ab1268ea4651343624387679022026203223c9a2968530f2af4a16bb079fee2905cc5cbba258f1f823603e57c89501004cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff8f27f1cd8b0b7cce783346f0538bee9397641b87d37d96a22fd8c3476146a62301000000fd5e0100483045022100b8e4ebf749ab4bba66e55e857a07b834558a16aeecd93d6e007811456d78d0b302205a8cbcc8f63f118536f938894f3a27236c353a177c43c0ef9987b29bac3227ef0147304402206390095bade6a4159ad036d9cfe7e7f0004024da09d460784d8bb45806664e62022059d21c421e1ddcdb17d70998617af6fc85589b35f6bd7c423d5443da4ec4864201004cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff0200752b7d0000000017a91413d2d93195352467f94a12a3def1e4c09d15ac278778d5a4350000000017a914cce437c88256ca0a9fa1eed83e5b192f4dcc39f18700000000",
46  "status":200
47}
48*/
49
50// 第三个普通地址进行第三次签名并广播交易
51curl "192.168.7.44:3004/confirm?txid=97adab60d7a0f71fca8f22b0007ef9b0b3f8eb1ce10341b4a5ee998d0bfbec72,9244f24ec81630742591a15007e84d6e113db259340e5ac319e6d38440baf89f,23a6466147c3d82fa2967dd3871b649793ee8b53f0463378ce7c0b8bcdf1278f&from=1GKhpdfXHUC1mBM6WrD63tbKvMUyj9irdb&signtx=020000000372ecfb0b8d99eea5b44103e11cebf8b3b0f97e00b0228fca1ff7a0d760abad9701000000fd5f01004830450221009c1518665cdb11e4e0d55e23fcbb19030c22ceaec081f646be0e8d062622df4c022037364e73584aee4fa9b8d26311039408f1d272b6e4955f0aaa377dc1090b87bb01483045022100b277e07d37f98f1c97dccf92f7c6bb7093622301d33bee48c57bb6fda687c068022066f1cafe7296fb57053577c1c3705b39dcfaa9f010c9699b20ad1cd98f0c549601004cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff9ff8ba4084d3e619c35a0e3459b23d116e4de80750a19125743016c84ef2449200000000fd5d0100473044022010ad85ee4f66b63c7765ccbdee57c66c9c37dee0965be4c5934e3e7f9b453e5102205089c146899a6228ba9acb12e714fb15f50619fccb99fe279d7aaa90489f39380147304402203062597d764932cd85ec9e5f82a6d471984d0d03ab1268ea4651343624387679022026203223c9a2968530f2af4a16bb079fee2905cc5cbba258f1f823603e57c89501004cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff8f27f1cd8b0b7cce783346f0538bee9397641b87d37d96a22fd8c3476146a62301000000fd5e0100483045022100b8e4ebf749ab4bba66e55e857a07b834558a16aeecd93d6e007811456d78d0b302205a8cbcc8f63f118536f938894f3a27236c353a177c43c0ef9987b29bac3227ef0147304402206390095bade6a4159ad036d9cfe7e7f0004024da09d460784d8bb45806664e62022059d21c421e1ddcdb17d70998617af6fc85589b35f6bd7c423d5443da4ec4864201004cc9534104362119e29a90c958c89efc186a23bb859c2d5de57cb0a6a9480ea47087f508d9fe0eceeaa42aec7d0757049c5395aaa1aeebc6b2babd3d1a9ca09122b8890f4c4104cc1f24bb27e7897c483e73d39542f578ec458f33ceea96cfed59ec5ae1b8474cbb3f96badd66caa134cdbc3c8d67ee4c424ea779414ad74383974761a8386a3541045b64a0d78f107a2525beaf4ede77b4bbabba671a86bfc37bc425382c85abb06c5cc4251cef05fd793491c4184db4601b69697eec12a4cb5199dc11f5a772ac6953aeffffffff0200752b7d0000000017a91413d2d93195352467f94a12a3def1e4c09d15ac278778d5a4350000000017a914cce437c88256ca0a9fa1eed83e5b192f4dcc39f18700000000"
52
53/*
54{
55  "result":true,
56  "sign_tx":"21ba06597c14339d7819511e5b4aa07834b503f1bce1d2141964a00c9a16d26e",
57  "status":200
58}
59*/
60
61// regtest 环境开启挖矿,确认多签交易
62bitcoin-cli -regtest generatetoaddress 10 2N8i6PbrW5nNtGbrHcPf5FJ1tNSyBou6t2b
63
64// regtest 查询 receiveaddress 地址余额
65bitcoin-cli -regtest getbalance  receiveaddress // 21.00000000

版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2018-11-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏比原链

Bytom 技术 FAQ

Gitee地址:https://gitee.com/BytomBlockchain/bytom

10810
来自专栏比原链

剥开比原看代码07:比原节点收到“请求区块数据”的信息后如何应答?

Gitee地址:https://gitee.com/BytomBlockchain/bytom

9320
来自专栏友弟技术工作室

solidity语言介绍以及开发环境准备

38030
来自专栏酷玩时刻

支付宝Wap支付你了解多少?

为了方便开发者生成一对RSA密钥支付宝提供一键生成工具,具体如何生成与配置密钥详见签名专区。

40120
来自专栏编程

区块链技术(二):以太坊编程语言Solidity安装及入门初体验

安装 如果你想测试一段简单的Solidity合约,你不需要安装任何东西,只要访问基于浏览器的Solidity就可以: https://chriseth.gith...

233100
来自专栏姚志锋的专栏

Android 开发: 小工具,大效率

首先申明下,此Hugo非 彼Hugo(Hugo是由Go语言实现的静态网站生成器)。本文主要介绍几种比较 nice 的插件和工具,有利于改善代码质量及效率提高.

4K10
来自专栏华仔的技术笔记

在Spectrum测试链用Truffle启动第一个宠物商店Dapp

在光谱链上实现一个Dapp,就是合约部署完之后(有一个我们可以直接与他交互的后端),然后做这个应用层的代码和后端的交互,给DApp加上前端数据交互、读取的界面。

26930
来自专栏Android 研究

OKHttp源码解析(九):OKHTTP连接中三个"核心"RealConnection、ConnectionPool、StreamAllocation

RealConnection是Connection的实现类,代表着链接socket的链路,如果拥有了一个RealConnection就代表了我们已经跟服务器有了...

66960
来自专栏为数不多的Android技巧

Android插件化原理解析——广播的管理

在Activity生命周期管理 以及 插件加载机制 中我们详细讲述了插件化过程中对于Activity组件的处理方式,为了实现Activity的插件化我们付出了相...

11020
来自专栏友弟技术工作室

solidity语言介绍以及开发环境准备

Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。这门语言受到了 C++,Python 和 Javascript 语言的影响,设计的目的是...

39240

扫码关注云+社区

领取腾讯云代金券