Despliegue rápido y llamada de la red de alianza abierta JD Zhizhen Chain

Prefacio:

Recientemente, quiero usar la cadena de bloques para el almacenamiento de certificados, y luego vi la red de alianza abierta JD Zhizhen Chain, así que me enteré y luego decidí escribir un código para llamarlo para el almacenamiento de certificados. Es gratis.

Se recomienda conocer la red de alianzas abiertas de JD Zhizhen Chain antes de leer este artículo .

Después de completar el registro, puede continuar después de iniciar sesión.

1. Crea tu primer contrato:

Para crear una subcuenta:

Gestión de contratos => Mi contrato inteligente => Haga clic en Crear => Agregar cuenta de subempresa

marca de agua, type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR54ix6K6p5py65Zmo5a2m5Lmg,size_20,color_FFFFFF,t_70,g_se,x_16

marca de agua, type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR54ix6K6p5py65Zmo5a2m5Lmg,size_20,color_FFFFFF,t_70,g_se,x_16

 Seleccione Clave no administrada, luego descargue la clave y guárdela para llamadas posteriores.

Crea tu primer contrato inteligente:

Regrese a la página del contrato inteligente, haga clic en "Crear contrato" en "Mi contrato inteligente".

Para la subcuenta, seleccione la subcuenta que acaba de crear y complete el resto según sus propios deseos.

marca de agua, type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR54ix6K6p5py65Zmo5a2m5Lmg,size_20,color_FFFFFF,t_70,g_se,x_16

La plantilla es la primera plantilla de depósito de certificado universal que elegí, y puedo elegirla según mis propias necesidades.

marca de agua, type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR54ix6K6p5py65Zmo5a2m5Lmg,size_20,color_FFFFFF,t_70,g_se,x_16

Luego hay nuevos campos.

El campo de índice es la clave principal, que configuré como 'id'. Por supuesto, complete el diseño aquí de acuerdo con sus propias necesidades. Solo configuré un campo para facilitar las pruebas.

marca de agua, type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR54ix6K6p5py65Zmo5a2m5Lmg,size_20,color_FFFFFF,t_70,g_se,x_16

 2. Implementación del código de firma:

Después de que el contrato se haya creado con éxito => llamar => llamar al desarrollador, podemos ver los documentos de desarrollo proporcionados por JD.

La documentación provista por JD tiene algunas trampas y algunos lugares están un poco equivocados.

Sin embargo, se recomienda que primero eche un vistazo al proceso general.

Durante todo el proceso, se utilizan dos firmas, una es la firma local (clave pública + clave privada + marca de tiempo) y la otra es la firma de la transacción (clave pública + clave privada + hash de la transacción). Todos se realizan llamando al SDK de escritura de Java proporcionado por JD, así que los encapsulé juntos. Si no sabe cómo usar Python para llamar a jar, primero puede leer mi artículo, Portal .

La clave pública y la clave privada están en el key.txt descargado al crear una subcuenta. Haga clic en SDK para llamar => desarrollador para llamar y haga clic en "Descargar SDK" en el primer paso oficial.

SignName.py

from jpype import *
import jpype
import time

class SignName:
    """
    调用京东提供的SDK,实现本地签名,交易签名
    * @param01: publicKey 公钥原文
    * @param02: privateKey 私钥原文
    
    """
    def __init__(self,publicKey:str,privateKey:str) -> None:
        jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=../jar/local-signature.jar")  #调用京东区块链的SDK
        self.__JDClass =jpype.JClass("com.jd.bt.chain.Signature") #这说明类在jar包中的目录结构是"com.jd.bt.chain.Signature"  数字签名
        self.__jdChain = self.__JDClass()  #实例化
        self.publicKey = publicKey
        self.privateKey = privateKey

    def localSign(self) -> str:

        """
        返回得到本地签名。
        调用SDK,signOrigin方法
        * @param01: timestamp 时间戳
        * @param02: publicKey 公钥原文
        * @param03: privateKey 私钥原文
        """
        self.timestampContent = str(round(time.time() * 1000))  #毫秒级时间戳
        self.result = str(self.__jdChain.signOrigin(self.timestampContent, self.publicKey,self.privateKey))  #子账户签名结果
        return self.result

    def transactionSign(self,txHash:str) -> str:

        """
        txHash:组装交易后的返回值中。
        返回得到交易签名。
        调用SDK,sign方法
        * @param01: txHash 交易哈希
        * @param02: publicKey 公钥原文
        * @param03: privateKey 私钥原文
        """

        self.result = str(self.__jdChain.sign(txHash, self.publicKey,self.privateKey))  #子账户签名结果
        return self.result
        

 3. Ficha de solicitud

Sin más preámbulos, vaya directamente al código. Simplemente use el método de obtención de solicitudes, la URL es: https://openchain.jd.com/server/account/getServerToken. Si no puede encontrar la didKey, consulte el primer paso del documento oficial de la llamada del desarrollador. Ahí está el valor de didKey, simplemente copie y pegue. La clave pública y la clave privada son las claves pública y privada de la sub- cuenta.

GetServerToken.py

import requests
import json
# from SignName import SignName

class GetServerToken:
    """
    token请求类
    """
    def __init__(self,publicKey:str,privateKey:str,didKey:str,signName) -> None:

        """
        * @param01:publicKey:子账户公钥
        * @param02:privateKey:子账户密钥
        * @param03:didKey:账户
        * @param04:SignName:签名类的实例化
        """
        self.publicKey = publicKey
        self.privateKey = privateKey
        self.didKey = didKey
        self.signName = signName


    def getURl(self,url='https://openchain.jd.com/server/account/getServerToken') -> dict:
        """
        请求的token
        * @param01:url:请求的网址
        """

        param = {
            'didKey':self.didKey,
            'subAccountPubKey':self.publicKey,
            'signature':self.signName.localSign(),   #子账户签名结果
            'timestamp':self.signName.timestampContent   #时间戳(被签名内容)
        }
        page = requests.get(url,params=param)
        msg = json.loads(page.text)
        return msg


# if __name__ == '__main__':
#     didKey = '填写自己的账户'
#     publicKey = '公钥'
#     privateKey = '私钥'
    
#     signName = SignName(publicKey,privateKey)
#     print(type(signName))
#     askToken = GetServerToken(publicKey,privateKey,didKey,signName)
#     msg = askToken.getURl()

#     print(msg)

Si necesita probar, simplemente abra el comentario en el parámetro correspondiente. El valor de retorno es el siguiente

626d5c7b770d4220a8412da37459a7bc.png

4. Transacción de montaje

El siguiente paso es armar la transacción, se utiliza el token y se debe sacar el token en el valor de retorno obtenido en el paso anterior. Simplemente use Publicar directamente después de los parámetros dados, url='https://openchain.jd.com/server/contract/call'

didPkPubK: DID información de identidad clave pública texto original, contractAddress: No se puede encontrar la dirección del contrato, y también se puede encontrar en el tercer paso del documento oficial.

Consulte el código para la implementación específica, y el código proporciona comentarios detallados. Nota: PrimaryKey: la clave principal necesaria para el almacenamiento de certificados. Significa que se almacenan los parámetros específicos, no el nombre del parámetro. No se equivoquen. Caí en eso al principio, y luego creé un contrato de subcuenta administrado y lo llamé directamente en la página, y luego F12 para verifique la solicitud que envió. Al mismo tiempo, si comete un error, él puede publicar y devolver el resultado. Tuve un problema en el último paso y encontré el hoyo aquí cuando regresé.

Llamadacontrato.py

import requests
import json
import sys
# from GetServerToken import GetServerToken
# from SignName import SignName

class ContractCall():
    """
    组装交易
    """

    def __init__(self,result:str,didKey:str,didPkPubK:str,publicKey:str,contractAddress:str,method:str,primaryKey:str,paramJson:dict={}) -> None:

        """
        * @param01:result:请求的token
        * @param02:didPkPubK:DID身份信息公钥原文
        * @param03:publicKey:调用合约用的子账户公钥,必须和签名用的子账户私钥是同一对秘钥
        * @param04:contractAddress:合约地址
        * @param05:method:调用方法(insert,query,update,insertOrUpdate四选一)
        * @param06:primaryKey:存证所需的主键。注:存的具体参数,非参数名!
        * @param07:paramJson:存证参数(按照数据格式的dict),调用insert和update方法时需要,query方法不需要
        """

        if result['code'] != 20000:
            print(f'获取Token失败:{result["msg"]}')
            sys.exit(1)
        self.token = result['data']['token']

        #请求头
        self.postHead = {
            'Gateway-Appid': didKey,
            'Gateway-Token': self.token,
        }

        self.postData = {
            'didPkPubK': didPkPubK,
            'subAccountPubKey': publicKey,  # 调用合约用的子账户公钥,必须和签名用的子账户私钥是同一对秘钥
            'contractAddress': contractAddress,
            'method': method,
            'primaryKey': primaryKey,
            'paramJson':  json.dumps(paramJson)
        }


    def postURL(self,url:str='https://openchain.jd.com/server/contract/call') -> dict:
        """
        组装交易后的返回值
        * @param01:url:请求的网址
        """

        page = requests.post(url, headers=self.postHead, json=self.postData) 
        msg = json.loads(page.text)
        return msg

        
# if __name__ == '__main__':

#     didKey = ''
#     publicKey = ''
#     privateKey = ''
#     didPkPubK = '' 
#     contractAddress = ''
#     method = 'insert' 
#     paramJson = {
#         'id' = 11
#     }
#     primaryKey = paramJson['id']  #存证所需的主键
#     signName = SignName(publicKey,privateKey)
#     getServerToken = GetServerToken(publicKey, privateKey, didKey,signName)
#     result = getServerToken.getURl()

#     contractCall = ContractCall(result,didKey,didPkPubK,publicKey,contractAddress,method,primaryKey,paramJson)
#     ans = contractCall.postURL()
#     print(ans)

 Ejemplo de valor de retorno:

{'código': 20000, 'msg': '操作成功', 'data': {'params': [{'address': 'LdeP5sRTSLNLpScahgrH51sfgVroJES2hAtjH', 'methodName': 'insert', 'key': 'wan' , 'paramJson': '{"name": "wan"}', 'paramType': 'String'}], 'txContent': '112JJhCfsgmv4pK6Xhd7WCbSiCYVepFAiMdabY3RN7sRotLhTHfKQZK4WPeanxfn9VpK3Tb5h3sAQ49bpx68NRj8ZoavrTNCEt9D515BFsKwouLEenXBDJRaGa1xMmJaexZxbXqChCuAV4HjV1Wrfz8DhrsqcQ5Ek1eTvHQ7HC8xbjALNw6w6YWpvRvtTUm3xkNTz7xc8AxbpPjEHAxYVUDE4rpgrjHK4Cv5SwiB2dEp2H', 'txHash': 'j5kd9kT62AqM97QVSX8pygL8DXv8S34Z4esMpyomVqnpWB', 'signerPubKey': '7VeRLfw1QyERWTPZmPJPKwiHUHGFJIUyK9XRsU2L9cL5vf6w' , 'firma': Ninguno}}

5. Transacción

último paso.

En el último paso del documento oficial, el nombre del parámetro 'signerPubKey' se escribió incorrectamente como 'publicKey'. Lo descubrí después de depurar con F12. He explicado el método específico en el paso anterior. Al mismo tiempo, el encabezado de la solicitud en el paso anterior es el mismo que esta vez, y los datos en el valor devuelto no son muy diferentes del parámetro json que necesitamos publicar. Solo necesitamos agregarle el resultado de nuestra firma de transacción. . url='https://openchain.jd.com/server/contract/sign'

Transacción.py

import requests
import json

# from GetServerToken import GetServerToken
# from ContractCall import ContractCall
# from SignName import SignName

class Transaction:
    """
    交易
    """
    def __init__(self,result:dict,postHead,signName) -> None:

        """
        * @param01: result 组装交易后的返回值
        * @param02:SignName:签名类的实例化
        """

        self.postHead = postHead
        self.data = result['data']
        self.txHash = result['data']['txHash']
        self.signName = signName
        self.signerPubKey = self.signName.transactionSign(self.txHash)
        self.data['signature'] = self.signerPubKey

    def postURL(self,url='https://openchain.jd.com/server/contract/sign') -> dict:
        """
        最终交易后的返回值
        * @param01:url:请求的网址
        """
        
        page = requests.post(url, headers=self.postHead,json=self.data) 
        msg = json.loads(page.text)
        return msg

# if __name__ == '__main__':

#     didKey = '
#     publicKey = ''
#     privateKey = ''
#     didPkPubK = '' 
#     contractAddress = ''
#     method = 'insert' 
#     paramJson = {
#         
#     }
#     signName = SignName(publicKey,privateKey)
#     primaryKey = paramJson['id'] 
#     getServerToken = GetServerToken(publicKey, privateKey, didKey,signName)
#     result = getServerToken.getURl()

#     contractCall = ContractCall(result,didKey,didPkPubK,publicKey,contractAddress,method,primaryKey,paramJson)
#     ans = contractCall.postURL()
#     transaction = Transaction(ans,contractCall.postHead,signName)
#     ans = transaction.postURL()
#     print(ans)

Ejemplo de valor de retorno:

{

"código": 20000,

"msg": "Operación exitosa",

"datos": {

"transacciónHash": "j5pMNEQolpWgX1y1m2q37CWkBD1yQfQcpvVSVuNb5fftpd",

"altura del bloque": "507",

"contenido": "{\"xingMing\":\"update1204\",\"zhuJian\":2}",

"hora": "2020-12-04 10:58:08",

}

}

Al mismo tiempo, también podemos hacer clic en la lista de datos en "Mi contrato inteligente" para consultar la información de la cadena en este momento.

 

Supongo que te gusta

Origin blog.csdn.net/youngwyj/article/details/124395161
Recomendado
Clasificación