Resumen del problema de Hyperledger Fabric 2.4.1 2.3.3 (actualizado continuamente)
Ubuntu 20.04
Hyperledger Fabric 2.3.3
SDK correspondiente Go 1.17.5
Chaincode correspondiente Go 1.18
Fabric-sdk-go 1.0.0
Docker 20.10.12
Docker-Compose 2.11.2
1. Después de enviar el código de cadena, hay un error al llamar a la función de contrato y el ID de canal está vacío:
comando de llamada:
peer chaincode invoque -o localhost:7050 – ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example. com-cert.pem --channelID cychannel --name matrimonio --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca .crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{“función”:“ Registro”, “Args”:[“1001”,“jack”]}'
Se produce el siguiente error:
Error: el parámetro requerido 'channelID' está vacío. Vuelva a ejecutar el comando con el indicador -C
razón:
Hay un problema con la sangría del comando llamado (los comandos son propensos a errores cuando se copian de la máquina local a la virtual), y no debe haber espacios después de --
Después de resolver:
2023-01-03 21:54:08.247 CST 0001 INFO [chaincodeCmd] chaincodeInvokeOrQuery -> Invocación de Chaincode exitosa. resultado: estado: 200
2. Después de enviar el código de cadena, hay un error al llamar a la función de contrato, el código de estado es 500 y el código de cadena no está instalado:
comando de llamada:
consulta de código de cadena del par -C cychannel -n matrimonio -c '{“Args”:[“searchMarriageInfoByClientId”,“1001”]}'
Se produce el siguiente error:
Error: error de aprobación durante la consulta. respuesta: estado: 500 mensaje: "asegúrese de que el matrimonio de código de cadena se haya definido correctamente en el canal cychannel e intente nuevamente: la definición de código de cadena para 'matrimonio' existe, pero el código de cadena no está instalado"
razón:
Este error ocurre cuando el código de cadena se envía con éxito. La razón es que el nombre de la función comienza con minúsculas, lo que solo es válido para llamar dentro de este paquete y no se puede llamar externamente. Simplemente cambie el nombre de la función para que comience con mayúsculas.
Después de resolver:
{“id”:“1001”,“matrimonio_id”:“”,“nombre_persona”:“jack”,“está_casado”:falso}
Suplemento: Este problema también ocurre en otra situación
escena:
El host local llama al código de cadena del servidor remoto en la nube a través del Go-SDK (el cortafuegos ha abierto los puertos TCP 7051 y 9051).
razón:
Agregué juicio de permiso en la función de código de cadena (solo pueden acceder los clientes con certificados org1):
como resultado, cuando inicialicé el objeto del contrato en el SDK, usé el certificado de org2. Por lo tanto, elimine el archivo de billetera generado (este paso es crítico) y modifique todo org2 en el código a org1, y tendrá éxito.
3. Cuando el SDK local llama al código de cadena del host remoto, se informa un error, la conexión está en TRANSIENT_FAILURE:
Se produce el siguiente error:
La creación del servicio de eventos falló: no se pudo obtener la referencia de caché de chConfig: QueryBlockConfig falló: QueryBlockConfig falló: queryChaincode falló: Procesamiento de transacciones para el endosante [192.168.6.149:7051]: Código de estado del cliente del endosante: (2) CONNECTION_FAILED. Descripción: marcando la conexión en el destino [192.168.6.149:7051]: la conexión está en TRANSIENT_FAILURE
razón:
La estructura de mi proyecto SDK local es la siguiente:
el archivo de configuración que utilizo está bajo test-network bajo fabric-samples, y se deben preparar tres cosas con anticipación:
① Modificar la url de connection-org1.yaml en las organizaciones locales para la IP del host remoto:
② Agregue la resolución del nombre de dominio del host remoto en el archivo de hosts locales.
③ Cada vez que el código de cadena se implementa con éxito, las organizaciones del proyecto local deben actualizarse desde la red de prueba (una organización solo se puede usar para un proyecto SDK).
Después de asegurarse de que el trabajo anterior es correcto, ejecute main.go para llamar al código de cadena remoto e informar un error...
La razón es que fabric-sdk-go no es compatible con fabric2.4.x, y el problema se resuelve correctamente. resuelto después de reemplazarlo con fabric2.3.3.
(Si desea usar la versión 2.4.x, debe usar el nuevo sdk: fabric-gateway, cuya dirección de Github es https://github.com/hyperledger/fabric-gateway)
4. El SDK local llama al código de cadena del host remoto e informa un error, la configuración de MSP falló: sanitizeCert falló, la identidad proporcionada no es válida: x509: certificado firmado por una autoridad desconocida:
razón:
Problema con la versión de Go, mi versión local de Go es 1.19.2, después de cambiar a 1.17.5, el problema está resuelto.
Después de resolver:
El SDK finalmente se inició con éxito y el código de cadena remoto se puede llamar normalmente.
5. Al crear un canal, el comando ./network.sh up createChannel informa de un error y el mensaje de error es osnadmin: error: unknown long flag '–channel -id', try --help
Solución:
Debe modificar el archivo createChannel.sh en fabric-samples/test-network/scripts y cambiar –channel-id en la función createChannel a –channelID
6. Al llamar al código de cadena del host remoto a través del SDK, se informa un error: UTC - lazyref.(*Reference).refreshValue -> WARN Error - error devuelto por el inicializador: error al cargar MSP desde la configuración: error al configurar MSP: error al sanitizeCert la identidad suministrada no es válida: x509: certificado firmado por una autoridad desconocida. Se volverá a intentar más tarde
Solución:
Sigue siendo un problema con la versión Go. Después de reemplazar Go 1.19.2 con Go 1.17.5, el problema se resolvió.
7. ¿Cómo establece el SDK la ruta de generación de la billetera?
Solución:
monedero, err := gateway.NewFileSystemWallet(“org1/wallet”)
8. No se pudo invocar el código de cadena
Mensaje de error:
Error: error de aprobación durante la invocación. respuesta: estado: 500 mensaje: "error en la simulación: no se pudo ejecutar la transacción 306ed1ca53720d68d6e392198014ca2e91fbfa79a9f6e6be7a7e40f497bf4b1e: no se pudo iniciar chaincode rent_1.0: e678092929f2e636a5bcb1ddbfd52dd04c4 5b1fc5128a2a4cf883cb5c7991ee9: falló el registro del código de cadena: el contenedor salió con 2”
razón:
El problema con el código de cadena en sí. Cada función chaincode tiene un receptor de tipo puntero, y la instancia correspondiente es un contrato que hereda contractapi.Contract. Y accidentalmente escribí la instancia como una estructura personalizada, lo que provocó un error.
Solución:
Contrato definido:
error:
correcto:
9. En el código de la cadena, el problema de la versión contractapi
go mod tidy importa la última versión de forma predeterminada. A partir de ahora (2023.03.17), la última versión de contractapi es 1.2.1, que requiere que la versión de go sea superior a 1.19 (hace un mes, la última versión de contractapi era 1.2.0, que admite go 1.18 y no ocurrirá este problema), y mi go local es la versión 1.18, por lo que habrá un error al instalar el código de cadena.
Y después de cambiar la versión de go a la 1.19, hubo un error inesperado al instalar el código de la cadena... Por lo tanto, solo puedo modificar la versión de contractapi para admitir la versión inferior de go. Dado que la versión go de la máquina virtual donde se encuentra mi chaincode es 1.18, cambié la versión de contractapi a 1.2.0 (1.2.0 requiere que la versión go sea superior a 1.17), que es compatible.
module xxx
go 1.18
require github.com/hyperledger/fabric-contract-api-go v1.2.0
require (
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/spec v0.20.6 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/gobuffalo/envy v1.10.1 // indirect
github.com/gobuffalo/packd v1.0.1 // indirect
github.com/gobuffalo/packr v1.30.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/hyperledger/fabric-chaincode-go v0.0.0-20220720122508-9207360bbddd // indirect
github.com/hyperledger/fabric-protos-go v0.0.0-20220613214546-bf864f01d75e // indirect
github.com/joho/godotenv v1.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20220719170305-83ca9fad585f // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
10. El SDK local no pudo acceder al código de cadena en el servidor
Mensaje de error:
“Error al enviar: Ocurrieron varios errores: - Procesamiento de transacciones para el endosante [localhost:7051]: Código de estado del cliente del endosante: (2) CONNECTION_FAILED. Descripción: marcando la conexión en el destino [localhost:7051]: la conexión está en TRANSIENT_FAILURE - Procesamiento de transacciones para el endosante [localhost:9051]: Código de estado del cliente del endosante: (2) CONNECTION_FAILED. Descripción: marcando la conexión en el destino [localhost:9051]: la conexión está en TRANSIENT_FAILURE”
Solución:
Establezca DISCOVERY_AS_LOCALHOST en falso en el SDK; de lo contrario, se enviará una solicitud al local y el código de cadena se colocará en el servidor, al que obviamente es imposible acceder.
11. El SDK local no pudo acceder al código de cadena en el servidor
Mensaje de error:
pánico: Error al enviar: CreateAndSendTransaction falló: SendTransaction falló: llamar al ordenante 'orderer.example.com:7050' falló: Código de estado del cliente del ordenante: (2) CONNECTION_FAILED. Descripción: conexión de marcación en el destino [orderer.example.com:7050]: espera de conexión fallida: límite de contexto excedido [recuperado]
pánico: Error al enviar: CreateAndSendTransaction falló: SendTransaction falló: llamada orderer 'orderer.example.com:7050' fallido: código de estado del cliente del pedido: (2) CONNECTION_FAILED. Descripción: marcando la conexión en el destino [orderer.example.com:7050]: falló la espera de la conexión: se excedió la fecha límite del contexto
analizar:
Mirando el mensaje de error, parece que el acceso al nodo del ordenador falló, resultó que el servidor no abrió el puerto 7050.
Solución:
abrir puerto de servidor
Un problema similar surge en otra situación:
Agregué la resolución de nombre de dominio de múltiples servidores en el archivo de host local, es decir, el nombre de dominio de la misma organización corresponde a múltiples IP. Debe asegurarse de que la ip en el archivo del host sea la ip del servidor donde se encuentra el código de cadena al que desea acceder.
12. Después de volver a abrir una terminal, ¿cómo llamar a la función chaincode?
método:
PWD='/myFabric/fabric-samples/test-network'
exportar RUTA=${PWD}/…/bin:$RUTA
exportar FABRIC_CFG_PATH=${PWD}/…/config/
exportar CORE_PEER_TLS_ENABLED=verdadero
exportar CORE_PEER_LOCALMSPID=“Org1MSP”
exportar CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
exportar CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
exportar CORE_PEER_ADDRESS=localhost:7051
Después de configurar las variables de entorno anteriores, simplemente llame a la función chaincode desde la línea de comando.
13. ¿Cómo convertir el segmento de carácter obtenido a través de la consulta SDK en un objeto?
método:
Para una cadena json que representa un solo objeto, deserialice a map[string]interface{};
para una cadena json que represente una matriz de objetos, deserialice a []map[string]interface{};
//根据用户ID获取该用户的缴税记录
taxes, err := utils.TaxContract.EvaluateTransaction("GetAllTaxesByUserId", userId)
if err != nil {
return err
}
var res []map[string]interface{
}
json.Unmarshal(taxes, &res)
fmt.Println(res)