Criar e Implantar o Contrato Inteligente

Para criar o contrato inteligente, precisamos definir as entidades a serem armazenadas e gerenciadas no Blockchain, conforme mostrado no modelo de entidade da imagem a seguir.


A seguir, descrição de oracle-blockchain-cms-entity.png
Descrição da ilustração oracle-blockchain-cms-entity.png

Todas essas entidades e suas relações, toda a lógica necessária para gerenciar e interagir com as entidades e também para persisti-las no razão blockchain é definida no contrato inteligente.

A pasta é representada como um token NFT, por isso será desenvolvida e inicializada como um NFT. As outras entidades dependentes (Documentos e Propriedades), são entidades padrão e são entidades filho da pasta, portanto, serão desenvolvidas como entidades padrão sem a necessidade de inicialização.

Uma vez que o contrato inteligente é criado, vamos instalá-lo e implantá-lo na Rede Blockchain que criamos.

Criar o Contrato Inteligente

Depois de configurar o Oracle Blockchain App Builder, você poderá criar o arquivo de especificação. O arquivo de especificação pode ser criado como um arquivo YAML simples mostrado no código a seguir.

Observação:

Você também pode fazer download desse arquivo em GitHub: Fazer download do arquivo YAML.
#
# Token asset to manage the complete lifecycle of a non-fungible token representing a folder to hold docuements. 
# This specification file will generate an Smartcontract project with a non-fungible token for the folders to be maintained by the users.
#
assets:
    - name: folderNFT
      type: token
      symbol: eDocs
      standard: erc721+
      anatomy: 
        type: nonfungible
        unit: whole
      behavior:
        - indivisible
        - singleton
        - mintable:
        - transferable
        - burnable
        - roles:
            minter_role_name: minter
      properties:
          - name: folderHASH
            type: string
          - name: documents
            type: document[]
      metadata:
          - name: folderID
            type: string
            mandatory: true
            id: true
          - name: folderType
            type: string
            mandatory: true
      methods:
        crud: [create, getById, update, delete]
        others: [getHistoryById, getByRange]
    - name: document
      properties:
        - name: docName
          type: string
          mandatory: true
          id: true
        - name: docURL
          type: string
          mandatory: true
        - name: docHASH
          type: string
          mandatory: true
        - name: docType
          type: string
          mandatory: true
        - name: docProperties
          type: docProperty[]
      methods:
        crud: [create, getById, update, delete]
        others: [getHistoryById, getByRange]
    - name: docProperty
      type: embedded
      properties:
          - name: propName
            type: string
            mandatory: true
          - name: propValue
            type: string
            mandatory: true
      methods:
        crud: [create, getById, update, delete]
        others: [getHistoryById, getByRange]
customMethods:
    - executeQuery
    - "attachDocument(tokenId: string, docName: string, docURL: string, docHASH: string, docType: string, docProps: string[], docVals: string[])" # Attach a document to an existing folder. 
    - "retrieveDocuments(tokenId: string)" # Retrieve Documents of an folder. 
    - "transferFolder(tokenId: string, fromOrgId: string, fromUserId: string, toOrgId: string, toUserId: string)" # Transfer the folder among participants. 
    - "updateFolderHASH(tokenId: string, newHash: string)" # Update HASH folder 
    - "getFolderHASH(tokenId: string)" # Check HASH folder 

Neste arquivo de especificação, na primeira entidade definida (folderNFT), você pode ver todas as seções e atributos para a representação de um token NFT. Visão geral das seções definidas no arquivo:

  • Ativos: Coloque onde os diferentes ativos (entidades padrão, transações financeiras, NFTs) são definidos. Dentro de cada um dos ativos, podemos distinguir diferentes seções que podem variar dependendo do tipo de ativo representado. Para NFTs e FTs, estas são as diferentes subseções:
    • Tipo/Símbolo/Padrão: Especifique se esse token se baseia no Padrão ERC-721 e dê a ele um indentificador de símbolo exclusivo.
    • Anatomia: Especifique se é um NFT e se está subdividido em frações menores (hoje, "todo" é a única opção para tokens NFT).
    • Comportamento: Define se o token pode ser cunhado e, nesse caso, qual é o número máximo de tokens minimizáveis. Aqui você também deve declarar que é um token indivisível, se é singleton para cada classe, transferível e queimável que é semelhante à sua exclusão (mas não desaparecendo, então ainda está lá, mas não utilizável). Também nesta seção, você pode restringir o comportamento do token a funções específicas.
    • Metadados: Define uma espécie de propriedades que devem ser definidas durante a criação do token e não podem ser alteradas no futuro. Assim, seu valor permanecerá imutável por toda a vida do token.
    • Propriedades: Define atributos padrão do token que podem variar durante a vida útil do token, como o array de documentos que compõem a pasta.
  • customMethods: Local no qual a lista de nossos métodos personalizados deve ser definida. Para esses métodos, o Oracle Blockchain App Builder só gerará a assinatura do método, sem qualquer implementação neles. A implementação desses métodos é o único código que pode ser implementado pelo desenvolvedor.

Os links a seguir descrevem como configurar qualquer tipo de entidade (NFT, FT ou entidades padrão) com base em suas necessidades de negócios:

Depois que o arquivo de especificação tiver sido criado, poderemos exigir que o Oracle Blockchain App Builder crie o andaime do projeto seguindo estas próximas etapas.

  1. Se o arquivo de especificação tiver sido criado fora do Oracle Blockchain App Builder, importe o arquivo de especificação para o Oracle Blockchain App Builder. Clique nas reticências ao lado do quadro ESPECIFICAÇÕES e, no pop-up, clique em Importar Especificação.
  2. Selecione o arquivo de especificação e clique em Importar Especificação.
  3. Para criar um novo projeto de chaincode com base no arquivo de especificação importado, clique no ícone + no canto superior direito do quadro CHAINCODES. Ele abrirá o assistente Criar Chaincode.
  4. No assistente Criar Chaincode, especifique os seguintes detalhes:
    • Nome: Nome do projeto.
    • Idioma: Idioma para criar o andaime do projeto. Você só pode selecionar entre Typescript e GoLang. Como estamos usando Typescript neste manual de soluções para a implementação dos métodos personalizados, recomendamos selecionar Typescript.
    • Especificação: Selecione o arquivo de especificação que acabamos de criar nas etapas anteriores.
    • Local/Domínio: Dependendo do idioma selecionado, você será solicitado a definir o local em que o projeto será colocado para o idioma Typescript ou o domínio para o idioma GoLang.
    Se todos os detalhes estiverem corretos, veremos uma mensagem verde no assistente. Se este não for o caso, verifique a saída gerada durante a criação do andaime do projeto.
  5. Na seção CHAINCODES, devemos ver o novo projeto gerado. Clicando no projeto, navegue até a pasta src dentro do projeto, onde o código-fonte foi gerado:
    • Dentro da pasta src/controller, veremos a classe principal que representa nosso contrato inteligente, com todos os métodos gerados automaticamente para gerenciar nossas entidades.
    • Dentro da pasta src/model, veremos a classe que representa a entidade NFT.
  6. Navegue até a pasta src/controller e selecione a classe do controlador. Veremos todo o código gerado automaticamente pelo Oracle Blockchain App Builder e, ao final do arquivo, veremos todas as assinaturas dos métodos personalizados sem qualquer implementação neles.
  7. Neste ponto, devemos criar a implementação dos métodos personalizados. Para simplificar, fornecemos todo o código de implementação desses métodos no arquivo CMS_customMethods.ts, disponível em GitHub. Você só precisa substituir o conteúdo do arquivo referenciado pelas assinaturas geradas automaticamente pelo Oracle Blockchain App Builder.
A classe Controladora, linhas antes dos métodos personalizados, inclui todo o código gerado automaticamente para gerenciar o ciclo de vida dos tokens NFT. A imagem a seguir mostra as diferentes áreas cobertas por esses métodos.

oracle-blockchain-nft-token-oracle.zip

Neste ponto, o chaincode está pronto para ser usado, para que possamos implantar e testar o chaincode localmente seguindo as instruções de Testar Seu Chaincode em uma Rede Local do Hyperledger Fabric.

Implantar o Contrato Inteligente

Depois de testarmos localmente o chaincode, prossiga para implantá-lo na rede real criada anteriormente usando a Console do Oracle Blockchain Service:

  • Empacotando o projeto do chaincode.
  • Instalando e Implantando o pacote chaincode na instância única (fundador).
A seção a seguir descreve as etapas detalhadas para executar a implantação.
  1. Crie o pacote implantável a partir do projeto chaincode. No Visual Studio, clique no botão direito na parte superior do nome do projeto do chaincode. No menu pop-up, selecione a opção Pacote e selecione o diretório para salvar o arquivo do pacote chaincode.
  2. Acesse a Console do Oracle Blockchain Service para instalar e implantar o pacote de chaincode na instância do fundador.
  3. Navegue até a guia Código de Cadeia e clique em Implantar um Novo Código de Cadeia.
  4. Selecione a opção Implantação Avançada.
  5. Defina todos os valores para instalar o pacote de chaincode na instância do fundador e clique em Próximo.
    • Rótulo do Pacote: Forneça um nome que possa ajudá-lo a identificar qual pacote está instalado nos diferentes canais existentes. Como você pode ter mais de uma versão do mesmo contrato inteligente implantada em diferentes canais, é uma boa prática definir um nome de rótulo de pacote como:
      <smartContractName>_<channel>_<version>
      
    • Idioma do Código de Cadeia: selecione entre os diferentes idiomas, com base no idioma em que você desenvolveu o código de cadeia.
    • Pares de Destino: Selecione os pares nos quais você deseja instalar o pacote de chaincode.
    • Chaincode Empacotado: Deixe esta caixa de seleção desmarcada se você estiver fazendo upload de um arquivo zip. Marque a caixa de seleção para arquivos tar.gz.
    • Origem do Código de Cadeia: Clique em Fazer Upload do Arquivo de Código de Cadeia e selecione o arquivo zip do código de cadeia.
  6. Se a instalação for bem-sucedida, veremos a mensagem de sucesso. A próxima etapa é a implantação do chaincode no canal selecionado; portanto, você deve definir todos os valores relacionados à fase de implantação e clicar em Próximo.
    • Canal: Selecione o canal no qual você deseja implantar o contrato inteligente.
    • Nome do Código de Cadeia: Defina o nome com o qual o contrato inteligente será implantado no canal.
    • Versão: Atribua um número a esta implantação, que está alinhada com o pacote instalado anteriormente. Dessa forma, você poderá correlacionar pacotes instalados com chaincodes implantados em diferentes canais.
    • Init-required: Marque essa caixa de seleção se o método init do chaincode precisar ser chamado antes de permitir transações do usuário.
    • Política de Endosso: Especifique políticas de endosso durante a implantação. Neste exemplo do manual de soluções, não estamos usando políticas de endosso.
    • Coleta de Dados Privados: Defina Coletas de Dados Privados, se necessário. Neste exemplo de manual de soluções, não definiremos a coleta de dados privada.
Se a implantação for bem-sucedida, após fechar a instalação e a implantação, você deverá ver como o pacote foi instalado nos dois pares da instância e também instanciado em um dos canais.

Inicializar o Contrato Inteligente

Quando você está lidando com FTs e tokens NFT, há um conjunto de ações administrativas a serem executadas antes de poder executar seus métodos de negócios. Com o Oracle Blockchain, todas as tarefas administrativas podem ser executadas como chamadas REST simples e reduz consideravelmente o esforço necessário para inicializar o contrato inteligente.

Observação:

Antes de executar qualquer uma das etapas a seguir, devemos criar o enrollmentIDs nos Proxies REST para os usuários que receberam acesso aos métodos de contrato inteligente. A inscrição é um mapeamento entre o nome de usuário que chama a API REST e as contas gerenciadas internamente pelo blockchain às quais os tokens serão atribuídos, conforme descrito no tópico Criar inscrições nos nós Proxy REST.

Use a seguinte coleção Postman para inicializar facilmente o contrato inteligente: Fazer Download da coleção Postman

Na pasta AdminSteps desta coleção Postman, há três chamadas de solicitação a serem executadas para a inicialização do contrato inteligente.

A coleção Postman está pronta para ser usada, mas há um conjunto de variáveis que precisam ser configuradas adequadamente para seu próprio ambiente (senhas, URLs e assim por diante). Essas variáveis são definidas na guia Variáveis da coleção Postman. A tabela a seguir mostra todas as variáveis que definimos e que precisam ser adaptadas ao seu ambiente.

Nome da Variável Valor da variável
bc_founder_provider_url https://org1-w....
bc_timeout 60,000
bc_nft_founder_userid1 cmsleg001
bc_nft_founder_userid1_pwd senha
bc_nft_founder_userid2 cmsfin001
bc_nft_founder_userid2_pwd senha
bc_nft_founder_userid3 cmsrsk001
bc_nft_founder_userid4_pwd senha
bc_channel_name wedocms
bc_chaincode_name CUNHA

Localize o ponto final no qual a API REST está acessível na Console do Serviço Blockchain.

  1. Acesse a Console do Serviço Blockchain por meio da Console do OCI.
  2. Vá para a guia Nós. Ele mostrará todos os nós que compõem essa instância e, no nó restproxy, você verá o URL do ponto final na coluna Rota.
    Lembre-se de que as inscrições são criadas no nível da instância, não no nível da rede; portanto, a inscrição do usuário só estará disponível por meio do URL restproxy da instância do fundador; portanto, se novas instâncias entrarem na rede, com novos usuários autorizados a acessar a rede, esses usuários precisarão existir na tenancy adequada, e as inscrições desses usuários também deverão ser criadas no restproxy da instância correspondente.
Uma vez que a coleção Postman tenha sido configurada corretamente, podemos prosseguir com a inicialização do contrato inteligente. A inicialização de um contrato inteligente NFT é consideravelmente mais simples do que a inicialização de um contrato inteligente FT, só precisamos executar três etapas:
  1. Inicialização de contrato inteligente (Contas de Usuário do Administrador de Entrada).
  2. Criação de carteiras para usuários que podem possuir os tokens NFT.
  3. Designe a atribuição de minter aos usuários que devem ter esse privilégio.
As chamadas REST de API a seguir correspondem às chamadas na pasta AdminSteps da coleção Postman fornecida.
  1. Inicialize o chaincode (Etapa-0: Iniciar Conta de Usuário Admin) indicando quais contas de usuário terão permissão para executar tarefas administrativas. É importante definir os argumentos do método init corretamente: args: Scaped array of user_ids with their org_ids.
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}",
        "args": [
            "init",
            "[{\"orgId\":\"org1\",\"userId\":\"cmsleg001\"},{\"orgId\":\"org1\",\"userId\":\"cmsfin001\"},{\"orgId\":\"org1\",\"userId\":\"cmsrsk001\"}]"
        ],
        "timeout": {{bc_timeout}},
        "isInit": true,
        "sync": true
    }
    
  2. Crie contas de usuário para todos os usuários que podem ser depositários dos ativos NFT que representam os ativos físicos. Isso pode ser feito executando a solicitação Postman da Etapa 1: Criar conta. Para as especificidades do nosso caso de uso, existem apenas três usuários relacionados com a mesma organização única pertencente à rede. Essa chamada deve ser executada tantas vezes quanto os usuários para os quais queremos criar uma conta. No nosso caso três vezes, cada um com os seguintes parâmetros:
    • "createAccount", "org1", "cmsleg001", "nonfungible"
    • "createAccount", "org1", "cmsfin001", "nonfungible"
    • "createAccount", "org1", "cmsrsk001", "nonfungible"
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}", //Smartcontract name
        "args": [
            "createAccount", "org1","cmsleg001","nonfungible" //Method, OrgID, UserID, fungible for FT / nonfungible for NFT
        ],
        "timeout": 60000,
        "sync": true
    }
    
  3. Defina qual usuário tem permissão para cunhar tokens. Nesse caso, cunhar um token significa criar uma nova pasta para conter um novo conjunto de documentos, para que você possa decidir qual dos três usuários existentes (cmsleg001, cmsfin001 ou cmsrsk001) pode executar essas ações e, para esses usuários, execute a solicitação Etapa 2: AddRole da coleção Postman.
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}", //Smartcontract name
        "args": [
            "addRole", //Method name
            "minter","org1","cmsleg001" //Role, OrgId, UserID
            ],
        "timeout": 60000,
        "sync": true
    }