日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

智能合約Java開發(fā)指南

更新時(shí)間:

本節(jié)介紹如何使用Java語言進(jìn)行智能合約的開發(fā)。

鏈碼結(jié)構(gòu)

在Java語言中,鏈碼主要由以下方法組成。

/**
 * Defines methods that all chaincodes must implement.
 */
public interface Chaincode {
    /**
     *Called during an instantiate transaction after the container has been 
     *established, allowing the chaincode to initialize its internal data
     */
    public Response init(ChaincodeStub stub);
    /**
     *Called for every Invoke transaction. The chaincode may change its state 
     *variables.
     */
    public Response invoke(ChaincodeStub stub);
}
  • init: 鏈碼在初始化和升級(jí)時(shí)調(diào)用此接口,初始化相關(guān)的數(shù)據(jù)。

  • invoke:主要用于實(shí)現(xiàn)鏈碼的內(nèi)部業(yè)務(wù)邏輯,您可以在該方法中實(shí)現(xiàn)相關(guān)的業(yè)務(wù)。

  • 在上述方法實(shí)現(xiàn)過程中,用戶可以調(diào)用 ChaincodeStubImpl 的 API 接口和鏈上進(jìn)行交互。

鏈碼示例

Hyperledger Fabric 提供了很多官方鏈碼樣例,具體請(qǐng)參考fabric 官方示例。 我們以 Hyperledger Fabric 官方提供的 example02 樣例為例,為大家介紹鏈碼的開發(fā)規(guī)范。

簡單示例

首先,我們看一個(gè)空鏈碼結(jié)構(gòu)的示例代碼

import java.util.List;

import com.google.protobuf.ByteString;
import io.netty.handler.ssl.OpenSsl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperledger.fabric.shim.ChaincodeBase;
import org.hyperledger.fabric.shim.ChaincodeStub;

import static java.nio.charset.StandardCharsets.UTF_8;

/*
 * 一個(gè)管理資產(chǎn)的簡單鏈碼
 */
public class SimpleAssetDemo extends ChaincodeBase {
    /*
     * 在鏈碼實(shí)例化期時(shí)調(diào)用Init初始化數(shù)據(jù)
     */
    @Override
    public Response init(ChaincodeStub stub) {
    }
    /*
     * Invoke在每一筆交易時(shí)都會(huì)被調(diào)用,該方法應(yīng)該包含 set 以及 get 來創(chuàng)建和獲取對(duì)應(yīng)的鍵值
     */
    @Override
    public Response invoke(ChaincodeStub stub) {
    }
    public static void main(String[] args) {
        new SimpleAssetDemo().start(args);
    }
}

init 示例

Init 函數(shù)在鏈碼實(shí)例化以及升級(jí)的時(shí)候會(huì)被調(diào)用。在實(shí)現(xiàn) Init 函數(shù)的過程中,可使用 Java 語言版本的合約 API 列表來對(duì)參數(shù)和分布式賬本進(jìn)行操作。

@Override
public Response init(ChaincodeStub stub) {
    try {
        _logger.info("Init java simple chaincode");
        // 調(diào)用 getFunction 方法獲取當(dāng)前調(diào)用的函數(shù)
        String func = stub.getFunction();
        if (!func.equals("init")) {
            return newErrorResponse("function other than init is not supported");
        }
        // 調(diào)用API getParameters 獲取調(diào)用的參數(shù)
        List<String> args = stub.getParameters();
        if (args.size() != 4) {
            return newErrorResponse("Incorrect number of arguments. Expecting 4");
        }
        // 初始化相關(guān)數(shù)據(jù)
        String account1Key = args.get(0);
        int account1Value = Integer.parseInt(args.get(1));
        String account2Key = args.get(2);
        int account2Value = Integer.parseInt(args.get(3));

        _logger.info(String.format("account %s, value = %s; account %s, value %s", account1Key, account1Value, account2Key, account2Value));
        // 調(diào)用 putStringState 方法將數(shù)據(jù)寫入賬本中
        stub.putStringState(account1Key, args.get(1));
        stub.putStringState(account2Key, args.get(3));

        return newSuccessResponse();
    } catch (Throwable e) {
        return newErrorResponse(e);
    }
}

本示例要求用戶輸入的參數(shù)為KEY1_NAME, VALUE1, KEY2_NAME, VALUE2,并初始化2個(gè)鍵值對(duì),調(diào)用 putStringState 將數(shù)據(jù)寫入分布式賬本中。

invoke 示例

invoke 函數(shù)是對(duì)用戶具體業(yè)務(wù)邏輯的實(shí)現(xiàn),用戶可以根據(jù)不同的業(yè)務(wù)處理邏輯,調(diào)用不同的業(yè)務(wù)處理函數(shù),如invoke,delete 和 query 函數(shù)。

// invoke把用戶調(diào)用的function細(xì)分到幾個(gè)子function, 包含invoke,delete和query
@Override
public Response invoke(ChaincodeStub stub) {
    try {
        _logger.info("Invoke java simple chaincode");
        String func = stub.getFunction();
        List<String> params = stub.getParameters();
        if (func.equals("invoke")) {
            return invoke(stub, params);
        }
        if (func.equals("delete")) {
            return delete(stub, params);
        }
        if (func.equals("query")) {
            return query(stub, params);
        }
        return newErrorResponse("Invalid invoke function name. Expecting one of: [\"invoke\", \"delete\", \"query\"]");
    } catch (Throwable e) {
        return newErrorResponse(e);
    }
}
invoke 函數(shù)

業(yè)務(wù)邏輯 invoke 函數(shù)實(shí)現(xiàn)了業(yè)務(wù)邏輯中的資產(chǎn)轉(zhuǎn)移,將 accountFrom 的資產(chǎn)轉(zhuǎn)移 amount 個(gè)單位給 accountTo。

// invoke實(shí)現(xiàn)了兩個(gè)鍵之間的value轉(zhuǎn)移,輸入?yún)?shù)為KEY1_NAME, KEY2_NAME,VALUE
private Response invoke(ChaincodeStub stub, List<String> args) {
    if (args.size() != 3) {
        return newErrorResponse("Incorrect number of arguments. Expecting 3");
    }
    String accountFromKey = args.get(0);
    String accountToKey = args.get(1);
    // 獲取accountFromKey的當(dāng)前資產(chǎn)情況
    String accountFromValueStr = stub.getStringState(accountFromKey);
    if (accountFromValueStr == null) {
        return newErrorResponse(String.format("Entity %s not found", accountFromKey));
    }
    int accountFromValue = Integer.parseInt(accountFromValueStr);

    // 獲取accountToKey的當(dāng)前資產(chǎn)情況
    String accountToValueStr = stub.getStringState(accountToKey);
    if (accountToValueStr == null) {
        return newErrorResponse(String.format("Entity %s not found", accountToKey));
    }
    int accountToValue = Integer.parseInt(accountToValueStr);

    int amount = Integer.parseInt(args.get(2));

    if (amount > accountFromValue) {
        return newErrorResponse(String.format("not enough money in account %s", accountFromKey));
    }

    // 業(yè)務(wù)邏輯:實(shí)現(xiàn)資產(chǎn)的轉(zhuǎn)移
    accountFromValue -= amount;
    accountToValue += amount;

    _logger.info(String.format("new value of A: %s", accountFromValue));
    _logger.info(String.format("new value of B: %s", accountToValue));

    // 將更新后的資產(chǎn)更新到賬本中
    stub.putStringState(accountFromKey, Integer.toString(accountFromValue));
    stub.putStringState(accountToKey, Integer.toString(accountToValue));

    _logger.info("Transfer complete");

    return newSuccessResponse("invoke finished successfully", ByteString.copyFrom(accountFromKey + ": " + accountFromValue + " " + accountToKey + ": " + accountToValue, UTF_8).toByteArray());
}
  • 使用 API getStringState 獲取到 KEY_NAME 對(duì)應(yīng)的資產(chǎn)總值

  • 調(diào)用業(yè)務(wù)邏輯實(shí)現(xiàn) amount 個(gè)資產(chǎn)單位的轉(zhuǎn)移

  • 調(diào)用 API putStringState 將更新后的資產(chǎn)情況寫入到賬本中

重要

上述實(shí)現(xiàn)的是一個(gè)類似轉(zhuǎn)賬的簡單邏輯,但并未對(duì)參數(shù)的合法性諸如轉(zhuǎn)賬金額大于零、余額不為負(fù)等進(jìn)行校驗(yàn)。

delete 函數(shù)

業(yè)務(wù)邏輯 delete 函數(shù)實(shí)現(xiàn)了業(yè)務(wù)邏輯中的賬戶刪除功能。

// 從狀態(tài)中刪除實(shí)體
private Response delete(ChaincodeStub stub, List<String> args) {
    if (args.size() != 1) {
        return newErrorResponse("Incorrect number of arguments. Expecting 1");
    }
    String key = args.get(0);
    // 從分類帳中的狀態(tài)刪除密鑰
    stub.delState(key);
    return newSuccessResponse();
}

query 函數(shù)

業(yè)務(wù)邏輯 query 函數(shù)實(shí)現(xiàn)了業(yè)務(wù)邏輯中的賬戶查詢功能,通過調(diào)用 API GetState 查詢對(duì)應(yīng)賬戶的資產(chǎn)。

// query callback representing the query of a chaincode
private Response query(ChaincodeStub stub, List<String> args) {
    if (args.size() != 1) {
        return newErrorResponse("Incorrect number of arguments. Expecting name of the person to query");
    }
    String key = args.get(0);
    //byte[] stateBytes
    String val  = stub.getStringState(key);
    if (val == null) {
        return newErrorResponse(String.format("Error: state for %s is null", key));
    }
    _logger.info(String.format("Query Response:\nName: %s, Amount: %s\n", key, val));
    return newSuccessResponse(val, ByteString.copyFrom(val, UTF_8).toByteArray());
}