Могу ли я отправить предложение tx сразу 3 поддерживающим узлам, используя fabric-python-sdk в Hyperledger Fabric?

#hyperledger-fabric #hyperledger

#hyperledger-fabric #hyperledger

Вопрос:

  • Окружающая среда
    • Hyperledger Fabric v1.4.7 / fabric-python-sdk
    • Node1-Org1 (10.10.0.1), Node2-Org2 (10.10.0.2), Node3-Org3 (10.10.0.3)
    • Политика одобрения : AND ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')
  • network.json
 {
    "name": "net_fabric",
    "version": "1.0.0",
    "client": {
        "organization": "Org1",
        "credentialStore": {
            "path": "/tmp/hfc-kvs",
            "cryptoStore": {
                "path": "/tmp/hfc-cvs"
            },
            "wallet": "wallet-name"
        },
        "connection": {
            "timeout": {
                "peer": {
                    "endorser": "60000",
                    "eventHub": "60000",
                    "eventReg": "60000"
                },
                "orderer": "60000"
            }
        }
    },
    "channels": {
        "mychannel": {
            "orderers": [
                "orderer.example.com"
            ],
            "peers": {
                "peer0.org1.example.com": {
                "endorsingPeer": true,
                "chaincodeQuery": true,
                "eventSource": true
        },
                "peer1.org1.example.com": {
                "endorsingPeer": true,
                "chaincodeQuery": true,
                "eventSource": true
        },
                "peer0.org2.example.com": {
                "endorsingPeer": true,
                "chaincodeQuery": true,
                "eventSource": true
        },
                "peer1.org2.example.com": {
                "endorsingPeer": true,
                "chaincodeQuery": true,
                "eventSource": true
        },
                "peer0.org3.example.com": {
                "endorsingPeer": true,
                "chaincodeQuery": true,
                "eventSource": true
        },
                "peer1.org3.example.com": {
                "endorsingPeer": true,
                "chaincodeQuery": true,
                "eventSource": true
        }
            }
        }
    },
    "organizations": {
        "orderer.example.com": {
            "mspid": "OrdererMSP",
            "orderers": [
                "orderer.example.com"
            ],
            "users": {
                "Admin": {
                    "cert": "crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/Admin@example.com-cert.pem",
                    "private_key": "crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/keystore/bb970e6666e63f00039c25c15f82ac39860027ea3a353fa9152dedf508a68541_sk"
                }
            }
        },
        "org1.example.com": {
            "mspid": "Org1MSP",
            "peers": [
                "peer0.org1.example.com",
                "peer1.org1.example.com"
            ],
            "certificateAuthorities": [
                "ca.org1.example.com"
            ],
            "users": {
                "Admin": {
                    "cert": "crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem",
                    "private_key": "crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/9ed12a80062621bc68bcf6d73309cb216b6d72b8b4e4ae2aea5751d69bbead35_sk"
                },
                "User1": {
                    "cert": "crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem",
                    "private_key": "crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/1a476c5cc5874ae5a9b5c313e6fbd4cf4717d2730d4e0349668bc53ef4e05b93_sk"
                }
            }
        },
        "org2.example.com": {
            "mspid": "Org2MSP",
            "peers": [
                "peer0.org2.example.com",
                "peer1.org2.example.com"
            ],
            "certificateAuthorities": [
                "ca.org2.example.com"
            ],
            "users": {
                "Admin": {
                    "cert": "crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem",
                    "private_key": "crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/5d3223ea7355959ffe90185e149395ee972902bd6f4ac4ec240c855a2d61ed4a_sk"
                },
                "User1": {
                    "cert": "crypto-config/peerOrganizations/org2.example.com/users/User1@org2.example.com/msp/signcerts/User1@org2.example.com-cert.pem",
                    "private_key": "crypto-config/peerOrganizations/org2.example.com/users/User1@org2.example.com/msp/keystore/57b1ca82356ba68fdf93aa208da3c25f8055310dffacd61373946f2673bc4e96_sk"
                }
            }
        },
        "org3.example.com": {
            "mspid": "Org3MSP",
            "peers": [
                "peer0.org3.example.com",
                "peer1.org3.example.com"
            ],
            "certificateAuthorities": [
                "ca.org3.example.com"
            ],
            "users": {
                "Admin": {
                    "cert": "crypto-config/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp/signcerts/Admin@org3.example.com-cert.pem",
                    "private_key": "crypto-config/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp/keystore/570a370bfd2cea9ced433be8955c6676a6208d3ec5953df267781cf5ba6bf831_sk"
                },
                "User1": {
                    "cert": "crypto-config/peerOrganizations/org3.example.com/users/User1@org3.example.com/msp/signcerts/User1@org3.example.com-cert.pem",
                    "private_key": "crypto-config/peerOrganizations/org3.example.com/users/User1@org3.example.com/msp/keystore/e24c3bde2038a04bab26453083fd07433070e3cffccad5205ae319ce4d64fc47_sk"
                }
            }
        }
    },
    "orderers": {
        "orderer.example.com": {
            "url": "10.10.0.1:7050",
            "grpcOptions": {
                "grpc.ssl_target_name_override": "orderer.example.com",
                "grpc-max-send-message-length": 15
            }
        }
    },
    "peers": {
        "peer0.org1.example.com": {
            "url": "grpc://peer0.org1.example.com:7051",
            "grpcOptions": {
                "grpc.ssl_target_name_override": "peer0.org1.example.com",
                "grpc-max-send-message-length": 15
            }
        },
        "peer1.org1.example.com": {
            "url": "grpc://peer1.org1.example.com:7051",
            "grpcOptions": {
                "grpc.ssl_target_name_override": "peer1.org1.example.com",
                "grpc-max-send-message-length": 15
            }
        },
        "peer0.org2.example.com": {
            "url": "grpc://peer0.org2.example.com:7051",
            "grpcOptions": {
                "grpc.ssl_target_name_override": "peer0.org2.example.com",
                "grpc-max-send-message-length": 15
            }
        },
        "peer1.org2.example.com": {
            "url": "grpc://peer1.org2.example.com:7051",
            "grpcOptions": {
                "grpc.ssl_target_name_override": "peer1.org2.example.com",
                "grpc-max-send-message-length": 15
            }
        },
        "peer0.org3.example.com": {
            "url": "grpc://peer0.org3.example.com:7051",
            "grpcOptions": {
                "grpc.ssl_target_name_override": "peer0.org3.example.com",
                "grpc-max-send-message-length": 15
            }
        },
        "peer1.org3.example.com": {
            "url": "grpc://peer1.org3.example.com:7051",
            "grpcOptions": {
                "grpc.ssl_target_name_override": "peer1.org3.example.com",
                "grpc-max-send-message-length": 15
            }
        }
    },
    "certificateAuthorities": {
        "ca.org1.example.com": {
            "url": "http://ca.org1.example.com:7054",
            "caName": "ca.org1.example.com"
        },
        "ca.org2.example.com": {
            "url": "http://ca.org2.example.com:7054",
            "caName": "ca.org2.example.com"
        },
        "ca.org3.example.com": {
            "url": "http://ca.org3.example.com:7054",
            "caName": "ca.org3.example.com"
        }
    }
}
  

Я хочу отправить предложение tx сразу 3 поддерживающим узлам.

Я использую fabric-sdk-py amp; grpc для отправки транзакции, подобной этой:

 class GrpclbServicer(grpclb_pb2_grpc.GrpclbServicer):
    def Execute(self, request, context):
        org1_admin = cli.get_user(org_name='org1.example.com', name='Admin')
        # The response should be true if succeed
        response = loop.run_until_complete(cli.chaincode_invoke(
                            requestor=org1_admin,  
                            channel_name=request.channelName,  
                            peers=['peer0.org1.example.com','peer0.org2.example.com','peer0.org3.example.com'],   
                            fcn=request.functionName, # createCar
                            args=request.args,
                            cc_name=request.chaincodeName, # fabcar  
                            transient_map=None, # optional, for private data
                            wait_for_event=True, # for being sure chaincode invocation has been commited in the ledger, default is on tx event
                            ))
        return grpclb_pb2.TxResponse(
            response = response
        )
  

При chaincode_invoke выполнении можно выбрать только один запрос (org1_admin), чтобы я получил сообщение об ошибке, подобное этому. (org1_admin содержит только Org1MSP)

 2020-09-02 07:13:25.782 UTC [endorser] SimulateProposal -> ERRO 095 [mychannel][4bd53729] failed to invoke chaincode name:"fabcar" , error: txid: 4bd53729be43a4de95d5d6383fc9f6e2f610f05ea486815f75799839d1a8186c(mychannel) exists
  

Итак, я изменил код следующим образом:

     def Execute(self, request, context):
        orgs = ['org1.example.com','org2.example.com','org3.example.com']

        # The response should be true if succeed
        for org in orgs:
            org_admin = cli.get_user(org_name=org, name='Admin')
            response = loop.run_until_complete(cli.chaincode_invoke(
                                requestor=org_admin,  
                                channel_name=request.channelName,  
                                peers=['peer0.' org],
                                fcn=request.functionName,
                                args=request.args,
                                cc_name=request.chaincodeName,  
                                transient_map=None, # optional, for private data
                                wait_for_event=True, # for being sure chaincode invocation has been commited in the ledger, default is on tx event
                                ))
  

Но я получил эту ошибку. Я думаю … причина этой ошибки в том, что политика одобрения не выполняется, потому что tx отправляется один за другим.

 2020-09-02 07:29:09.205 UTC [vscc] Validate -> ERRO 06a VSCC error: stateBasedValidator.Validate failed, err validation of endorsement policy for chaincode fabcar in tx 6:0 failed: signature set did not satisfy policy
2020-09-02 07:29:09.205 UTC [committer.txvalidator] validateTx -> ERRO 06b VSCCValidateTx for transaction txId = 3ac7c00db44090924edb8bc88c543430e3b77e69856a8a7c22b7c9062eb2b4d8 returned error: validation of endorsement policy for chaincode fabcar in tx 6:0 failed: signature set did not satisfy policy
  

Есть ли способ отправить предложение Tx поддерживающим узлам (peer0.org1, peer0.org2, peer0.org3) сразу с помощью fabric-sdk-py?

Или как я могу выполнить политику одобрения?

Комментарии:

1. Поскольку каждый узел отделен от других, поэтому Fabric поддерживает параллельное одобрение. Проблема в том, как вы отправляете предложения узлам, и я знаю, что Python поддерживает многопоточность. Я могу сделать это с помощью Fabric-go-sdk, и я думаю, что Fabric-python-sdk тоже может

2. @HoaiNam Спасибо за ваш ответ. 1) Вы установили msp для каждой организации? ИЛИ просто установите 1 msp и поделитесь msp с другой организацией? 2) Не могли бы вы загрузить network.json или configtx.yaml файл?

3. У каждой организации есть свой собственный MSP. Я только что протестировал образец первой сети ( github.com/hyperledger/fabric-samples/tree/v2.1.0/first-network )

Ответ №1:

Это внутренний метод Fabric (Golang), но вы можете видеть, как они это делают, чтобы одновременно предлагать источнику сторонников

 // processProposals sends a signed proposal to a set of peers, and gathers all the responses.
func processProposals(endorserClients []pb.EndorserClient, signedProposal *pb.SignedProposal) ([]*pb.ProposalResponse, error) {
    responsesCh := make(chan *pb.ProposalResponse, len(endorserClients))
    errorCh := make(chan error, len(endorserClients))
    wg := sync.WaitGroup{}
    for _, endorser := range endorserClients {
        wg.Add(1)
        go func(endorser pb.EndorserClient) {       <=== This line creates a new thread for each endorser call
            defer wg.Done()
            proposalResp, err := endorser.ProcessProposal(context.Background(), signedProposal)
            if err != nil {
                errorCh <- err
                return
            }
            responsesCh <- proposalResp
        }(endorser)
    }
    wg.Wait()                              <=== And then wait until receiving all the responses
    close(responsesCh)
    close(errorCh)
    for err := range errorCh {
        return nil, err
    }
    var responses []*pb.ProposalResponse
    for response := range responsesCh {
        responses = append(responses, response)
    }
    return responses, nil
}
  

и я лично считаю, что вы можете сделать то же самое с Python

Комментарии:

1. Спасибо. Я изменил sdk python на golang… Знаете ли вы какие-либо руководства, на которые стоит ссылаться для версии 1.4? с fabric-sdk-go? Были только учебные пособия для версий до 1.4.

2. Грустно говорить вам, что документ go-sdk настолько плох :(. Если вы можете прочитать код Golang, я предлагаю вам ознакомиться с примерами fabric-sdk-go, такими как E2E Test ( github.com/hyperledger/fabric-sdk-go )

3. Итак, я переключился с go на node-sdk… Спасибо 🙂