zoukankan      html  css  js  c++  java
  • Fabric智能合约(余额转移样本)

    需求分析

    1)初始两个用户,赋予一定金额。

    2)转账

    3)查询余额

    4)删除账户


     go语言版

    项目结构

    项目代码

    package main
    
    import (
    	"fmt"
    	"strconv"
    
    	"github.com/hyperledger/fabric/core/chaincode/shim"
    	pb "github.com/hyperledger/fabric/protos/peer"
    )
    
    var logger = shim.NewLogger("example_cc0")
    
    // SimpleChaincode example simple Chaincode implementation
    type SimpleChaincode struct {
    }
    
    // Init initializes the chaincode state
    func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
    	logger.Info("########### example_cc Init ###########")
    
    	_, args := stub.GetFunctionAndParameters()
    	var A, B string    // Entities
    	var Aval, Bval int // Asset holdings
    	var err error
    
    	if len(args) != 4 {
    		return shim.Error("Incorrect number of arguments. Expecting 4")
    	}
    
    	// Initialize the chaincode
    	A = args[0]
    	Aval, err = strconv.Atoi(args[1])
    	if err != nil {
    		return shim.Error("Expecting integer value for asset holding")
    	}
    	B = args[2]
    	Bval, err = strconv.Atoi(args[3])
    	if err != nil {
    		return shim.Error("Expecting integer value for asset holding")
    	}
    	logger.Infof("Aval = %d, Bval = %d
    ", Aval, Bval)
    
    	// Write the state to the ledger
    	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
    	if err != nil {
    		return shim.Error(err.Error())
    	}
    
    	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
    	if err != nil {
    		return shim.Error(err.Error())
    	}
    
    	if transientMap, err := stub.GetTransient(); err == nil {
    
    		rc := transientMap["rc"]
    
    		transientData := transientMap["result"]
    
    		if rc == nil {
    			return shim.Success(transientData)
    		}
    
    		vrc, err := strconv.Atoi(string(rc[:]))
    
    		if err != nil {
    			return shim.Error(err.Error())
    		}
    
    		return pb.Response{
    			Status:  int32(vrc),
    			Payload: transientData,
    		}
    
    	}
    
    	return shim.Success(nil)
    }
    
    // Invoke makes payment of X units from A to B
    func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
    	logger.Info("########### example_cc Invoke ###########")
    
    	function, args := stub.GetFunctionAndParameters()
    
    	if function == "delete" {
    		// Deletes an entity from its state
    		return t.delete(stub, args)
    	}
    
    	if function == "move" {
    		// Deletes an entity from its state
    		return t.move(stub, args)
    	}
    
    	if function == "query" {
    		return t.query(stub, args)
    	}
    
    	logger.Errorf("Unknown action, check the first argument, must be one of 'delete', 'query', or 'move'. But got: %v", args[0])
    	return shim.Error(fmt.Sprintf("Unknown action, check the first argument, must be one of 'delete', 'query', or 'move'. But got: %v", args[0]))
    }
    
    func (t *SimpleChaincode) move(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    	// must be an invoke
    	var A, B string    // Entities
    	var Aval, Bval int // Asset holdings
    	var X int          // Transaction value
    	var err error
    
    	if len(args) != 3 {
    		return shim.Error("Incorrect number of arguments. Expecting 3, function followed by 2 names and 1 value")
    	}
    
    	A = args[0]
    	B = args[1]
    
    	// Get the state from the ledger
    	// TODO: will be nice to have a GetAllState call to ledger
    	Avalbytes, err := stub.GetState(A)
    	if err != nil {
    		return shim.Error("Failed to get state")
    	}
    	if Avalbytes == nil {
    		return shim.Error("Entity not found")
    	}
    	Aval, _ = strconv.Atoi(string(Avalbytes))
    
    	Bvalbytes, err := stub.GetState(B)
    	if err != nil {
    		return shim.Error("Failed to get state")
    	}
    	if Bvalbytes == nil {
    		return shim.Error("Entity not found")
    	}
    	Bval, _ = strconv.Atoi(string(Bvalbytes))
    
    	// Perform the execution
    	X, err = strconv.Atoi(args[2])
    	if err != nil {
    		return shim.Error("Invalid transaction amount, expecting a integer value")
    	}
    	Aval = Aval - X
    	Bval = Bval + X
    	logger.Infof("Aval = %d, Bval = %d
    ", Aval, Bval)
    
    	// Write the state back to the ledger
    	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
    	if err != nil {
    		return shim.Error(err.Error())
    	}
    
    	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
    	if err != nil {
    		return shim.Error(err.Error())
    	}
    
    	if transientMap, err := stub.GetTransient(); err == nil {
    		if transientData, ok := transientMap["event"]; ok {
    			stub.SetEvent("event", transientData)
    		}
    
    		rc := transientMap["rc"]
    
    		transientData := transientMap["result"]
    
    		if rc == nil {
    			return shim.Success(transientData)
    		}
    
    		vrc, err := strconv.Atoi(string(rc[:]))
    
    		if err != nil {
    			return shim.Error(err.Error())
    		}
    
    
    		logger.Infof("Status = %d 
    ", vrc)
    
    		return pb.Response{
    			Status:  int32(vrc),
    			Payload: transientData,
    		}
    	}
    
    	return shim.Success(nil)
    }
    
    // Deletes an entity from state
    func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    	if len(args) != 1 {
    		return shim.Error("Incorrect number of arguments. Expecting 1")
    	}
    
    	A := args[0]
    
    	// Delete the key from the state in ledger
    	err := stub.DelState(A)
    	if err != nil {
    		return shim.Error("Failed to delete state")
    	}
    
    	return shim.Success(nil)
    }
    
    // Query callback representing the query of a chaincode
    func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    
    	var A string // Entities
    	var err error
    
    	if len(args) != 1 {
    		return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
    	}
    
    	A = args[0]
    
    	// Get the state from the ledger
    	Avalbytes, err := stub.GetState(A)
    	if err != nil {
    		jsonResp := "{"Error":"Failed to get state for " + A + ""}"
    		return shim.Error(jsonResp)
    	}
    
    	if Avalbytes == nil {
    		jsonResp := "{"Error":"Nil amount for " + A + ""}"
    		return shim.Error(jsonResp)
    	}
    
    	jsonResp := "{"Name":"" + A + "","Amount":"" + string(Avalbytes) + ""}"
    	logger.Infof("Query Response:%s
    ", jsonResp)
    	return shim.Success(Avalbytes)
    }
    
    func main() {
    	err := shim.Start(new(SimpleChaincode))
    	if err != nil {
    		logger.Errorf("Error starting Simple chaincode: %s", err)
    	}
    }

    java语言版

    项目结构

     

    项目依赖

    1)build.gradle文件

    plugins {
        id 'com.github.johnrengelman.shadow' version '2.0.3'
        id 'java'
    }
    
    group 'org.hyperledger.fabric-chaincode-java'
    version '1.0-SNAPSHOT'
    
    sourceCompatibility = 1.8
    
    repositories {
        mavenLocal()
        mavenCentral()
    }
    
    dependencies {
        compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim', version: '1.4.1'
    }
    
    shadowJar {
        //这个名字必须是chaincode
        baseName = 'chaincode'
        version = null
        classifier = null
    
        manifest {
            attributes 'Main-Class': 'org.hyperledger.fabric.example.SimpleChaincode'
        }
    }

    2)settings.gradle文件

    rootProject.name = 'fabric-chaincode-example-gradle'

    项目代码

    package org.hyperledger.fabric.example;
    
    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;
    
    public class SimpleChaincode extends ChaincodeBase {
    
        private static Log _logger = LogFactory.getLog(SimpleChaincode.class);
    
        @Override
        public Response init(ChaincodeStub stub) {
            try {
                _logger.info("Init java simple chaincode");
                String func = stub.getFunction();
                if (!func.equals("init")) {
                    return newErrorResponse("function other than init is not supported");
                }
                List<String> args = stub.getParameters();
                if (args.size() != 4) {
                    newErrorResponse("Incorrect number of arguments. Expecting 4");
                }
                // Initialize the chaincode
                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));
                stub.putStringState(account1Key, args.get(1));
                stub.putStringState(account2Key, args.get(3));
    
                return newSuccessResponse();
            } catch (Throwable e) {
                return newErrorResponse(e);
            }
        }
    
        @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("move")) {
                    return move(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);
            }
        }
    
        private Response move(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);
    
            String accountFromValueStr = stub.getStringState(accountFromKey);
            if (accountFromValueStr == null) {
                return newErrorResponse(String.format("Entity %s not found", accountFromKey));
            }
            int accountFromValue = Integer.parseInt(accountFromValueStr);
    
            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));
            }
    
            accountFromValue -= amount;
            accountToValue += amount;
    
            _logger.info(String.format("new value of A: %s", accountFromValue));
            _logger.info(String.format("new value of B: %s", accountToValue));
    
            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());
        }
    
        // Deletes an entity from state
        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);
            // Delete the key from the state in ledger
            stub.delState(key);
            return newSuccessResponse();
        }
    
        // 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:
    Name: %s, Amount: %s
    ", key, val));
            return newSuccessResponse(val, ByteString.copyFrom(val, UTF_8).toByteArray());
        }
    
        public static void main(String[] args) {
            System.out.println("OpenSSL avaliable: " + OpenSsl.isAvailable());
            new SimpleChaincode().start(args);
        }
    }
  • 相关阅读:
    01_垂直居中body中的应用
    C++基础知识易错点总结(2)
    辗转相除求最大公约数
    C++基础知识易错点总结(1)
    类对象的建立方式总结
    LeetCode(131)Palindrome Partitioning
    基本套接字编程(7) -- udp篇
    LeetCode(124) Binary Tree Maximum Path Sum
    LeetCode(115) Distinct Subsequences
    LeetCode(97) Interleaving String
  • 原文地址:https://www.cnblogs.com/jockming/p/12208410.html
Copyright © 2011-2022 走看看