copay錢包(3.轉賬功能報文分析)

weixin_34124651發表於2018-05-09
5384456-1f611738691d15e1.png
set_wallet.png

建立tx報文

Request

Request URL: https://bws.bitpay.com/bws/api/v2/txproposals/
Request Method: POST
Status Code: 200

Request Header

x-identity: ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f
x-signature: 30440220112e0e2f0c47ad929ba96a2cf66e146508be54849b34f2ff9aa0e8e941d5febd02202cee1c2388076a9be937b788bbbccf1e59bc620421396142fbbfc19b74d04a06

Request Body

{
    "outputs": [{
        "toAddress": "2MtpsphTrgwZ6CmJrtZPmyUBJrKH9A8yijk",
        "amount": 200000,
        "message": null
    }],
    "feeLevel": "normal",
    "message": null,
    "excludeUnconfirmedUtxos": true,
    "dryRun": true,
    "payProUrl": null
}

Response Body

{
    "version": 3,
    "createdOn": 1525848972,
    "id": "0cb7f9ef-b416-4ff2-b717-7fc5e218ffd2",
    "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
    "creatorId": "ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f",
    "coin": "btc",
    "network": "testnet",
    "message": null,
    "payProUrl": null,
    "changeAddress": {
        "version": "1.0.0",
        "createdOn": 1525848972,
        "address": "2N9iPM2BCiZY9QhVXBvkwvVEPFA799pWPHk",
        "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
        "isChange": true,
        "path": "m/1/3",
        "publicKeys": ["036b550d9c5a5b385d55a1ed2f57a3523808877fe096aeff0f24d2d847267e0052", "03fa031596a39e82c8b2d40fceb6464b68e3156566c1e1c4f579eaf67b97bb2933"],
        "coin": "btc",
        "network": "testnet",
        "type": "P2SH"
    },
    "outputs": [{
        "amount": 200000,
        "toAddress": "2MtpsphTrgwZ6CmJrtZPmyUBJrKH9A8yijk",
        "message": null
    }],
    "outputOrder": [0, 1],
    "walletM": 1,
    "walletN": 2,
    "requiredSignatures": 1,
    "requiredRejections": 1,
    "status": "temporary",
    "actions": [],
    "feeLevel": "normal",
    "feePerKb": 1000,
    "excludeUnconfirmedUtxos": true,
    "addressType": "P2SH",
    "amount": 200000,
    "inputs": [{
        "txid": "e0f2ca534e9da941ac832eedbf5ec229408a43153aafb1356246e405463b7bfb",
        "vout": 0,
        "address": "2MtDw9oCLZ8mPp63CzwMH37ubKB7K2LtoQq",
        "scriptPubKey": "a9140ab9a7e6311a5ba83d11fff29d97290528d8665987",
        "satoshis": 985800,
        "confirmations": 7176,
        "locked": false,
        "path": "m/1/1",
        "publicKeys": ["03480e89ec9a061f60a7bcb6fd2fe423ccdde9b58662273cc0b8f41f1b0c6122ae", "02727fb32888be1dbc59a0786280fe5e6f77119258891cf5280fa89bf3c14be933"]
    }],
    "inputPaths": ["m/1/1"],
    "fee": 284
}

建立tx的交易,在pages/send/confirm頁面選擇傳送錢包時候觸發,呼叫的程式碼大致如下:

this.updateTx(this.tx, this.wallet, { dryRun: true }).catch((err: any) => {
      this.logger.warn('Error in updateTx: ', err);
    });

在updateTx()內部又呼叫了:

this.buildTxp(tx, wallet, opts).then(() => {
            this.onGoingProcessProvider.clear();
            return resolve();
          }).catch((err: any) => {
            this.onGoingProcessProvider.clear();
            return reject(err);
          });

最終,是由walletProvider向後臺服務請求生成交易

this.walletProvider.createTx(wallet, txp).then((ctxp: any) => {
        return resolve(ctxp);
      }).catch((err: any) => {
        this.setSendError(err);
        return reject(err);
      });

這裡最終呼叫了wallet-client的createTxProposal(),從請求報文可以看出,client端並沒有自己去生成這轉出交易,而是向server端傳送了必要的output資訊(接收地址,金額,備註),而是由server端根據這些配置,"代替"client端完成建立交易的工作.
P.S.client端並沒有向server傳送用那個哪戶轉出,server端是怎麼感知的呢?祕密在於Request Header的x-signature,該值是在構造wallet時候,由wallet公鑰生成的,而server器端儲存有wallet的資訊,所以只需要傳遞該值,server端就能自動判斷是哪個賬戶轉出的。

5384456-deb289d83ffd3e4a.png
send.png

建立tx報文(第二次)

Request

Request URL: https://bws.bitpay.com/bws/api/v2/txproposals/
Request Method: POST
Status Code: 200

Request Header

x-client-version: bwc-6.7.4
x-identity: ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f
x-signature: 30440220429565307510d449e5aa39fded3c7b7322642d6f932f72273f8e680abc227f0d02201fb1bf4785815768a8d2ac98cdcfc98228d94aa84ff0733f9228cfb9682d976d

Request Body

{
    "outputs": [{
        "toAddress": "2MtpsphTrgwZ6CmJrtZPmyUBJrKH9A8yijk",
        "amount": 200000,
        "message": null
    }],
    "feeLevel": "normal",
    "message": null,
    "excludeUnconfirmedUtxos": true,
    "dryRun": false,
    "payProUrl": null
}

Response Body

{
    "version": 3,
    "createdOn": 1525848985,
    "id": "1cdb4398-03da-4180-ab5e-97499a3623d4",
    "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
    "creatorId": "ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f",
    "coin": "btc",
    "network": "testnet",
    "message": null,
    "payProUrl": null,
    "changeAddress": {
        "version": "1.0.0",
        "createdOn": 1525848985,
        "address": "2N9iPM2BCiZY9QhVXBvkwvVEPFA799pWPHk",
        "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
        "isChange": true,
        "path": "m/1/3",
        "publicKeys": ["036b550d9c5a5b385d55a1ed2f57a3523808877fe096aeff0f24d2d847267e0052", "03fa031596a39e82c8b2d40fceb6464b68e3156566c1e1c4f579eaf67b97bb2933"],
        "coin": "btc",
        "network": "testnet",
        "type": "P2SH",
        "_id": "5af29b99bda304640dbd4ee0"
    },
    "outputs": [{
        "amount": 200000,
        "toAddress": "2MtpsphTrgwZ6CmJrtZPmyUBJrKH9A8yijk",
        "message": null
    }],
    "outputOrder": [1, 0],
    "walletM": 1,
    "walletN": 2,
    "requiredSignatures": 1,
    "requiredRejections": 1,
    "status": "temporary",
    "actions": [],
    "feeLevel": "normal",
    "feePerKb": 1000,
    "excludeUnconfirmedUtxos": true,
    "addressType": "P2SH",
    "amount": 200000,
    "inputs": [{
        "txid": "e0f2ca534e9da941ac832eedbf5ec229408a43153aafb1356246e405463b7bfb",
        "vout": 0,
        "address": "2MtDw9oCLZ8mPp63CzwMH37ubKB7K2LtoQq",
        "scriptPubKey": "a9140ab9a7e6311a5ba83d11fff29d97290528d8665987",
        "satoshis": 985800,
        "confirmations": 7176,
        "locked": false,
        "path": "m/1/1",
        "publicKeys": ["03480e89ec9a061f60a7bcb6fd2fe423ccdde9b58662273cc0b8f41f1b0c6122ae", "02727fb32888be1dbc59a0786280fe5e6f77119258891cf5280fa89bf3c14be933"]
    }],
    "inputPaths": ["m/1/1"],
    "fee": 284
}

在點選傳送按鈕後,

 public approve(tx: any, wallet: any): void {...
 }

在approve方法中,client會再次向server端申請create一次交易,當然,server還是會去生成一個
未用的hd地址作為change(由於第一次的沒有真實用,地址還是和第一次一樣的).但是由於建立的時間已經不同了,所以生成的tx-id是完全不同的.

5384456-50e8ef006567f077.png
confrim_send.png

推送tx報文

Request

Request URL: https://bws.bitpay.com/bws/api/v1/txproposals/1cdb4398-03da-4180-ab5e-97499a3623d4/publish/
Request Method: POST
Status Code: 200

Request Header

x-identity: ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f
x-signature: 30440220642fc81dfac718c3c382e204574ca5bc6c45742d07cd94465d5435cae2bc02d40220546d0b19bb2663f9fdfbd6ac4a836aeecb85246d82c971cc36603ccc9bcdd244

Request Body

{
    "proposalSignature": "3045022100c88e1997e6f7e3b2c7a57f90c561b91888475fc9d83c9b562a4c10f8d2b2589f02206d0961ddef78654ad012b49ffbb97d370b578c51c4fbe9adeadbe2257cfeb256"
}

Response Body

{
    "version": 3,
    "createdOn": 1525848985,
    "id": "1cdb4398-03da-4180-ab5e-97499a3623d4",
    "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
    "creatorId": "ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f",
    "coin": "btc",
    "network": "testnet",
    "outputs": [{
        "amount": 200000,
        "toAddress": "2MtpsphTrgwZ6CmJrtZPmyUBJrKH9A8yijk",
        "message": null
    }],
    "amount": 200000,
    "message": null,
    "payProUrl": null,
    "changeAddress": {
        "version": "1.0.0",
        "createdOn": 1525848985,
        "address": "2N9iPM2BCiZY9QhVXBvkwvVEPFA799pWPHk",
        "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
        "isChange": true,
        "path": "m/1/3",
        "publicKeys": ["036b550d9c5a5b385d55a1ed2f57a3523808877fe096aeff0f24d2d847267e0052", "03fa031596a39e82c8b2d40fceb6464b68e3156566c1e1c4f579eaf67b97bb2933"],
        "coin": "btc",
        "network": "testnet",
        "type": "P2SH",
        "hasActivity": null,
        "_id": "5af29b99bda304640dbd4ee0"
    },
    "inputs": [{
        "txid": "e0f2ca534e9da941ac832eedbf5ec229408a43153aafb1356246e405463b7bfb",
        "vout": 0,
        "address": "2MtDw9oCLZ8mPp63CzwMH37ubKB7K2LtoQq",
        "scriptPubKey": "a9140ab9a7e6311a5ba83d11fff29d97290528d8665987",
        "satoshis": 985800,
        "confirmations": 7176,
        "locked": false,
        "path": "m/1/1",
        "publicKeys": ["03480e89ec9a061f60a7bcb6fd2fe423ccdde9b58662273cc0b8f41f1b0c6122ae", "02727fb32888be1dbc59a0786280fe5e6f77119258891cf5280fa89bf3c14be933"]
    }],
    "walletM": 1,
    "walletN": 2,
    "requiredSignatures": 1,
    "requiredRejections": 1,
    "status": "pending",
    "inputPaths": ["m/1/1"],
    "actions": [],
    "outputOrder": [1, 0],
    "fee": 284,
    "feeLevel": "normal",
    "feePerKb": 1000,
    "excludeUnconfirmedUtxos": true,
    "addressType": "P2SH",
    "customData": null,
    "proposalSignature": "3045022100c88e1997e6f7e3b2c7a57f90c561b91888475fc9d83c9b562a4c10f8d2b2589f02206d0961ddef78654ad012b49ffbb97d370b578c51c4fbe9adeadbe2257cfeb256",
    "derivationStrategy": "BIP44",
    "creatorName": "{\"iv\":\"0Tx0HkyTJdQpsgXx2QAFoQ==\",\"v\":1,\"iter\":1,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"ct\":\"zdicqfgF5a0ccpAc/jMjR/UB\"}"
}

在點選傳送確認按鈕後,client端就開始真正的處理這個交易了,具體的呼叫過程為
approve()方法在呼叫this.popupProvider.ionicConfirm()彈出確認框後,構造並呼叫了自己"剛剛"宣告的publishAndSign()方法,其內部則呼叫了walletProvider的publishAndSign()方法實現.

      let publishAndSign = (): void => {
        if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
          this.logger.info('No signing proposal: No private key');
          this.onGoingProcessProvider.set('sendingTx');
          this.walletProvider.onlyPublish(wallet, txp).then(() => {
            this.onGoingProcessProvider.clear();
            this.openFinishModal(true);
          }).catch((err: any) => {
            this.onGoingProcessProvider.clear();
            this.setSendError(err);
          });
          return;
        }

        this.walletProvider.publishAndSign(wallet, txp).then((txp: any) => {
          this.onGoingProcessProvider.clear();
          if (this.config.confirmedTxsNotifications && this.config.confirmedTxsNotifications.enabled) {
            this.txConfirmNotificationProvider.subscribe(wallet, {
              txid: txp.txid
            });
          }
          this.openFinishModal();
        }).catch((err: any) => {
          this.onGoingProcessProvider.clear();
          this.setSendError(err);
          return;
        });
      };
      
this.walletProvider.publishAndSign(wallet, txp)

publishAndSign()可是一氣呵成完成了三個步驟,

// 釋出:
wallet.publishTxProposal(({txp},...)
// 簽名:
wallet.signTxProposal(txp, password, (err: any, signedTxp: any)
// 廣播:
wallet.broadcastTxProposal(txp, (err: any, broadcastedTxp: any, memo: any)

由於tx本身就是server端構造的,所以client僅需要在url中指出所對應的tx-id,並補充改步驟需要的資訊即可.

簽名tx報文

Request

Request URL: https://bws.bitpay.com/bws/api/v1/txproposals/1cdb4398-03da-4180-ab5e-97499a3623d4/signatures/
Request Method: POST
Status Code: 200

Request Header

x-identity: ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f
x-signature: 304402203cba7614d6aa2d8fc56ae64c626073e67f53d6ec0cd40a7747517a503af2435a02203117e45c6f7c2c65ccdc7e7f7d86557ab6e6ab866e18493cad73814085b9c955

Request Body

{
    "signatures": ["3044022047ea35be8583908a9994a7144642b628edaad70ad4c4fcb1a36056db55a40b9a022046a5bc8fb29de4c78cd4fc80ae59b27b3a240bbc10fc39e3fd422183d4f5e2e7"]
}

Response Body

{
    "version": 3,
    "createdOn": 1525848985,
    "id": "1cdb4398-03da-4180-ab5e-97499a3623d4",
    "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
    "creatorId": "ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f",
    "coin": "btc",
    "network": "testnet",
    "outputs": [{
        "amount": 200000,
        "toAddress": "2MtpsphTrgwZ6CmJrtZPmyUBJrKH9A8yijk",
        "message": null
    }],
    "amount": 200000,
    "message": null,
    "payProUrl": null,
    "changeAddress": {
        "version": "1.0.0",
        "createdOn": 1525848985,
        "address": "2N9iPM2BCiZY9QhVXBvkwvVEPFA799pWPHk",
        "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
        "isChange": true,
        "path": "m/1/3",
        "publicKeys": ["036b550d9c5a5b385d55a1ed2f57a3523808877fe096aeff0f24d2d847267e0052", "03fa031596a39e82c8b2d40fceb6464b68e3156566c1e1c4f579eaf67b97bb2933"],
        "coin": "btc",
        "network": "testnet",
        "type": "P2SH",
        "hasActivity": null,
        "_id": "5af29b99bda304640dbd4ee0"
    },
    "inputs": [{
        "txid": "e0f2ca534e9da941ac832eedbf5ec229408a43153aafb1356246e405463b7bfb",
        "vout": 0,
        "address": "2MtDw9oCLZ8mPp63CzwMH37ubKB7K2LtoQq",
        "scriptPubKey": "a9140ab9a7e6311a5ba83d11fff29d97290528d8665987",
        "satoshis": 985800,
        "confirmations": 7176,
        "locked": false,
        "path": "m/1/1",
        "publicKeys": ["03480e89ec9a061f60a7bcb6fd2fe423ccdde9b58662273cc0b8f41f1b0c6122ae", "02727fb32888be1dbc59a0786280fe5e6f77119258891cf5280fa89bf3c14be933"]
    }],
    "walletM": 1,
    "walletN": 2,
    "requiredSignatures": 1,
    "requiredRejections": 1,
    "status": "accepted",
    "txid": "9bd83411a7849f1546897472ac55e30df24c3700f7cc50b8e44a50b5885299ac",
    "broadcastedOn": null,
    "inputPaths": ["m/1/1"],
    "actions": [{
        "version": "1.0.0",
        "createdOn": 1525849013,
        "copayerId": "ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f",
        "type": "accept",
        "signatures": ["3044022047ea35be8583908a9994a7144642b628edaad70ad4c4fcb1a36056db55a40b9a022046a5bc8fb29de4c78cd4fc80ae59b27b3a240bbc10fc39e3fd422183d4f5e2e7"],
        "xpub": "tpubDDTZjjnaAsDHaD2CNQfsEKSmerbKjp9U5xXUj1UQCWnGLchBFMPM12bWf3izdTnocMA8cJXxwuYa9r8RyrK9GAhemaBEfGwDUiUEEA16rF5",
        "comment": null
    }],
    "outputOrder": [1, 0],
    "fee": 284,
    "feeLevel": "normal",
    "feePerKb": 1000,
    "excludeUnconfirmedUtxos": true,
    "addressType": "P2SH",
    "customData": null,
    "proposalSignature": "3045022100c88e1997e6f7e3b2c7a57f90c561b91888475fc9d83c9b562a4c10f8d2b2589f02206d0961ddef78654ad012b49ffbb97d370b578c51c4fbe9adeadbe2257cfeb256",
    "proposalSignaturePubKey": null,
    "proposalSignaturePubKeySig": null,
    "derivationStrategy": "BIP44",
    "creatorName": "{\"iv\":\"0Tx0HkyTJdQpsgXx2QAFoQ==\",\"v\":1,\"iter\":1,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"ct\":\"zdicqfgF5a0ccpAc/jMjR/UB\"}",
    "raw": "0100000001fb7b3b4605e4466235b1af3a15438a4029c25ebfed2e83ac41a99d4e53caf2e0000000009100473044022047ea35be8583908a9994a7144642b628edaad70ad4c4fcb1a36056db55a40b9a022046a5bc8fb29de4c78cd4fc80ae59b27b3a240bbc10fc39e3fd422183d4f5e2e70147512102727fb32888be1dbc59a0786280fe5e6f77119258891cf5280fa89bf3c14be9332103480e89ec9a061f60a7bcb6fd2fe423ccdde9b58662273cc0b8f41f1b0c6122ae52aeffffffff026cfc0b000000000017a914b4a50e0687fab537906032b585c1dbc90db425ac87400d03000000000017a91411556f743acba56e8a7ef30d78dcba5c05832ff18700000000"
}

廣播tx報文

Request

Request URL: https://bws.bitpay.com/bws/api/v1/txproposals/1cdb4398-03da-4180-ab5e-97499a3623d4/broadcast/
Request Method: POST
Status Code: 200

Request Header

x-identity: ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f
x-signature: 3044022035e6368be6e4fd075d1a13a2d77dec90735fa76d7a07e7580456f4c01632fb060220062f57175d286c2927363aae5bfd1af6fce812c4f039e4f63655425241341225

Request Body

{}

Response Body

{
    "version": 3,
    "createdOn": 1525848985,
    "id": "1cdb4398-03da-4180-ab5e-97499a3623d4",
    "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
    "creatorId": "ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f",
    "coin": "btc",
    "network": "testnet",
    "outputs": [{
        "amount": 200000,
        "toAddress": "2MtpsphTrgwZ6CmJrtZPmyUBJrKH9A8yijk",
        "message": null
    }],
    "amount": 200000,
    "message": null,
    "payProUrl": null,
    "changeAddress": {
        "version": "1.0.0",
        "createdOn": 1525848985,
        "address": "2N9iPM2BCiZY9QhVXBvkwvVEPFA799pWPHk",
        "walletId": "a887f15f-d0d5-42b5-a794-73bf92859b0e",
        "isChange": true,
        "path": "m/1/3",
        "publicKeys": ["036b550d9c5a5b385d55a1ed2f57a3523808877fe096aeff0f24d2d847267e0052", "03fa031596a39e82c8b2d40fceb6464b68e3156566c1e1c4f579eaf67b97bb2933"],
        "coin": "btc",
        "network": "testnet",
        "type": "P2SH",
        "hasActivity": null,
        "_id": "5af29b99bda304640dbd4ee0"
    },
    "inputs": [{
        "txid": "e0f2ca534e9da941ac832eedbf5ec229408a43153aafb1356246e405463b7bfb",
        "vout": 0,
        "address": "2MtDw9oCLZ8mPp63CzwMH37ubKB7K2LtoQq",
        "scriptPubKey": "a9140ab9a7e6311a5ba83d11fff29d97290528d8665987",
        "satoshis": 985800,
        "confirmations": 7176,
        "locked": false,
        "path": "m/1/1",
        "publicKeys": ["03480e89ec9a061f60a7bcb6fd2fe423ccdde9b58662273cc0b8f41f1b0c6122ae", "02727fb32888be1dbc59a0786280fe5e6f77119258891cf5280fa89bf3c14be933"]
    }],
    "walletM": 1,
    "walletN": 2,
    "requiredSignatures": 1,
    "requiredRejections": 1,
    "status": "broadcasted",
    "txid": "9bd83411a7849f1546897472ac55e30df24c3700f7cc50b8e44a50b5885299ac",
    "broadcastedOn": 1525849014,
    "inputPaths": ["m/1/1"],
    "actions": [{
        "version": "1.0.0",
        "createdOn": 1525849013,
        "copayerId": "ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f",
        "type": "accept",
        "signatures": ["3044022047ea35be8583908a9994a7144642b628edaad70ad4c4fcb1a36056db55a40b9a022046a5bc8fb29de4c78cd4fc80ae59b27b3a240bbc10fc39e3fd422183d4f5e2e7"],
        "xpub": "tpubDDTZjjnaAsDHaD2CNQfsEKSmerbKjp9U5xXUj1UQCWnGLchBFMPM12bWf3izdTnocMA8cJXxwuYa9r8RyrK9GAhemaBEfGwDUiUEEA16rF5",
        "comment": null,
        "copayerName": "{\"iv\":\"0Tx0HkyTJdQpsgXx2QAFoQ==\",\"v\":1,\"iter\":1,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"ct\":\"zdicqfgF5a0ccpAc/jMjR/UB\"}"
    }],
    "outputOrder": [1, 0],
    "fee": 284,
    "feeLevel": "normal",
    "feePerKb": 1000,
    "excludeUnconfirmedUtxos": true,
    "addressType": "P2SH",
    "customData": null,
    "proposalSignature": "3045022100c88e1997e6f7e3b2c7a57f90c561b91888475fc9d83c9b562a4c10f8d2b2589f02206d0961ddef78654ad012b49ffbb97d370b578c51c4fbe9adeadbe2257cfeb256",
    "proposalSignaturePubKey": null,
    "proposalSignaturePubKeySig": null,
    "derivationStrategy": "BIP44",
    "creatorName": "{\"iv\":\"0Tx0HkyTJdQpsgXx2QAFoQ==\",\"v\":1,\"iter\":1,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"ct\":\"zdicqfgF5a0ccpAc/jMjR/UB\"}",
    "raw": "0100000001fb7b3b4605e4466235b1af3a15438a4029c25ebfed2e83ac41a99d4e53caf2e0000000009100473044022047ea35be8583908a9994a7144642b628edaad70ad4c4fcb1a36056db55a40b9a022046a5bc8fb29de4c78cd4fc80ae59b27b3a240bbc10fc39e3fd422183d4f5e2e70147512102727fb32888be1dbc59a0786280fe5e6f77119258891cf5280fa89bf3c14be9332103480e89ec9a061f60a7bcb6fd2fe423ccdde9b58662273cc0b8f41f1b0c6122ae52aeffffffff026cfc0b000000000017a914b4a50e0687fab537906032b585c1dbc90db425ac87400d03000000000017a91411556f743acba56e8a7ef30d78dcba5c05832ff18700000000"
}

查詢tx

Request

Request URL: https://bws.bitpay.com/bws/api/v1/txconfirmations/
Request Method: POST
Status Code: 200

Request Header

x-identity: ff9c7ce1288026a4184018066bb74ccdb6b7c037d3de887b1378a81cbac1617f
x-signature: 304402203a6a23cd5dcbbe932bea06228bd0695c9939d65e7df65a9b68c603d492e7cd0502201be819417c6385062b06a337eaadddd671c90c478ed07f75ddcd82d29e85d292

Request Body

{
    "txid": "9bd83411a7849f1546897472ac55e30df24c3700f7cc50b8e44a50b5885299ac"
}

Response Body

{
    "ok": 1,
    "nModified": 0,
    "n": 1,
    "upserted": [{
        "index": 0,
        "_id": "5af29bb73834807db7f1b6e5"
    }],
    "lastOp": "6553471618058813445",
    "electionId": "5ac12a1d3834807db7d38cc1"
}

查詢請求是在完成publishAndSign之後,通過

this.txConfirmNotificationProvider.subscribe(wallet, {
              txid: txp.txid
            });

完成呼叫請求的.
這裡呼叫了client的

client.txConfirmationSubscribe(opts, (err: any, res: any)

從而完成交易確認的訂閱.

總結一下

總的來說,copay的交易建立,簽名和廣播都十分的依賴於server端,這大概與其自身實現的利用server完成多籤交易生成,感知,簽名流程有關,只有把一個多籤交易拆分能幾個不完整的子交易,並在網路上得以傳播才能實現.
目前,由於client也完整的引用了bitcore-lib,考慮在獲取足夠多的utxo前提下,在client端完成交易的生成,然後推送給client完成廣播.

相關文章