Fabric chaincode shim.ChaincodeStubInterface

1. 增改数据

    PutState(key string, value []byte) error

func (t *SimpleChaincode) push(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    // must be an invoke
    var A string    // Entities
    var Avalue string    // Transaction value
    var err error
    if len(args) != 2 {
        return shim.Error("Incorrect number of arguments. Expecting 4, function followed by 1 names and 1 value")
    }
    A = args[0]
    Avalue = args[1]
    // Write the state back to the ledger
    err = stub.PutState(A, []byte(Avalue))
    if err != nil {
        return shim.Error(err.Error())
    }
    return shim.Success(nil);
}

2. 删除数据

    DelState(key string) error

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)
}

3. 查询数据

    GetState(key string) ([]byte, error)

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\n", jsonResp)
    return shim.Success(Avalbytes)
}

4. 生成复合键

    CreateCompositeKey(objectType string, attributes []string) (string, error)

func (t *SimpleChaincode) pushComposite(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    // must be an invoke
    var A string    // Entities
    var Avalue string    // Transaction value
    var err error
    if len(args) != 2 {
        return shim.Error("Incorrect number of arguments. Expecting 4, function followed by 1 names and 1 value")
    }
    A = args[0]
    Avalue = args[1]  
    ck, cerr := stub.CreateCompositeKey("CompositeKey", []string{"compositeKey", A})
    if cerr != nil {
        return shim.Error(cerr.Error())
    }
    // Write the state back to the ledger
    err = stub.PutState(ck, []byte(Avalue))
    if err != nil {
        return shim.Error(err.Error())
    }
    return shim.Success(nil);
}

5. 拆分复合键

    SplitCompositeKey(compositeKey string) (string, []string, error)

6. 部分复合键查询

    GetStateByPartialCompositeKey(objectType string, keys []string) (StateQueryIteratorInterface, error)

func (t *SimpleChaincode) queryCompositeall(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    var buffer bytes.Buffer
    resultsIterator, err := stub.GetStateByPartialCompositeKey("CompositeKey", []string{"compositeKey"})
    if err != nil {
        return shim.Error(err.Error())
    }
    defer resultsIterator.Close() 
    for i := 0; resultsIterator.HasNext(); i++ {
        responseRange, err := resultsIterator.Next()
        if err != nil {
            return shim.Error(err.Error())
        }
        _, compositeKeyParts, err := stub.SplitCompositeKey(responseRange.Key)
        if err != nil {
            return shim.Error(err.Error())
        }
        returnedA := compositeKeyParts[1]
        buffer.WriteString(returnedA)
        buffer.Write([]byte(":"))
        buffer.Write(responseRange.Value)
        buffer.Write([]byte(","))
      }
    Avalbytes :=buffer.Bytes()
    return shim.Success(Avalbytes)
}

7. Key区间查询

GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error)

查询结果不包含endKey 。

func (t *SimpleChaincode) queryRang(stub shim.ChaincodeStubInterface, args []string) pb.Response {

    var starkey string
    var endkey string
    var buffer bytes.Buffer
    if len(args) != 2 {
        return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
    }   
    starkey = args[0]
    endkey = args[1]
    resultsIterator, err := stub.GetStateByRange(starkey, endkey)
    if err != nil {
        return shim.Error(err.Error())
    }
    defer resultsIterator.Close()
 
    for i := 0; resultsIterator.HasNext(); i++ {
        responseRange, err := resultsIterator.Next()
        if err != nil {
            return shim.Error(err.Error())
        }
        buffer.WriteString(responseRange.Key)
        buffer.Write([]byte(":"))
        buffer.Write(responseRange.Value)
        buffer.Write([]byte(","))
      }
    Avalbytes :=buffer.Bytes()
    return shim.Success(Avalbytes)

}

8. 富查询

GetQueryResult(query string) (StateQueryIteratorInterface, error)

是对Value的内容进行查询,如果是LevelDB,那么是不支持,只有CouchDB时才能用这个方法。
关于传入的query这个字符串,其实是CouchDB所使用的Mango查询,
我们可以在官方博客了解到一些信息:https://blog.couchdb.org/2016/08/03/feature-mango-query/ 
其基本语法可以在https://github.com/cloudant/mango 这里看到。

func (t *SimpleChaincode) queryResult(stub shim.ChaincodeStubInterface, args []string) pb.Response {

    var value string

    var buffer bytes.Buffer
    if len(args) != 1 {
        return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
    }

    value = args[0]

     //data[key, value]: ["*","{\"ID\":\"*\", \"Name\":\"*\"}"]

    queryString := fmt.Sprintf("{\"selector\":{\"Name\":\"%s\"}}", value)
    resultsIterator, err := stub.GetQueryResult(queryString)
    if err != nil {
        return shim.Error(err.Error())
    }
    defer resultsIterator.Close()
    for i := 0; resultsIterator.HasNext(); i++ {
        responseRange, err := resultsIterator.Next()
        if err != nil {
            return shim.Error(err.Error())
        }
        buffer.WriteString(responseRange.Key)
        buffer.Write([]byte(":"))
        buffer.Write(responseRange.Value)
        buffer.Write([]byte(","))
      }
    Avalbytes :=buffer.Bytes()
    return shim.Success(Avalbytes)

}

9. 历史数据查询

GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)

func (t *SimpleChaincode) queryHistory(stub shim.ChaincodeStubInterface, args []string) pb.Response {
    var key string
    var buffer bytes.Buffer
    if len(args) != 1 {
        return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
    }
    key = args[0]
    resultsIterator, err := stub.GetHistoryForKey(key)
    if err != nil {
        return shim.Error(err.Error())
    }
    defer resultsIterator.Close()
    buffer.WriteString(key)
    buffer.Write([]byte(":"))
    for i := 0; resultsIterator.HasNext(); i++ {
        responseRange, err := resultsIterator.Next()
        if err != nil {
            return shim.Error(err.Error())
        }
        buffer.Write(responseRange.Value)
        buffer.Write([]byte(","))
      }
    Avalbytes :=buffer.Bytes()
    return shim.Success(Avalbytes)
}

--------------------------------------------------------------------------------------------------------------

type ChaincodeStubInterface interface {
    // GetArgs returns the arguments intended for the chaincode Init and Invoke
    // as an array of byte arrays.
    GetArgs() [][]byte

    // GetStringArgs returns the arguments intended for the chaincode Init and
    // Invoke as a string array. Only use GetStringArgs if the client passes
    // arguments intended to be used as strings.
    GetStringArgs() []string

    // GetFunctionAndParameters returns the first argument as the function
    // name and the rest of the arguments as parameters in a string array.
    // Only use GetFunctionAndParameters if the client passes arguments intended
    // to be used as strings.
    GetFunctionAndParameters() (string, []string)

    // GetArgsSlice returns the arguments intended for the chaincode Init and
    // Invoke as a byte array
    GetArgsSlice() ([]byte, error)

    // GetTxID returns the tx_id of the transaction proposal, which is unique per
    // transaction and per client. See ChannelHeader in protos/common/common.proto
    // for further details.
    GetTxID() string

    // GetChannelID returns the channel the proposal is sent to for chaincode to process.
    // This would be the channel_id of the transaction proposal (see ChannelHeader
    // in protos/common/common.proto) except where the chaincode is calling another on
    // a different channel
    GetChannelID() string

    // InvokeChaincode locally calls the specified chaincode `Invoke` using the
    // same transaction context; that is, chaincode calling chaincode doesn't
    // create a new transaction message.
    // If the called chaincode is on the same channel, it simply adds the called
    // chaincode read set and write set to the calling transaction.
    // If the called chaincode is on a different channel,
    // only the Response is returned to the calling chaincode; any PutState calls
    // from the called chaincode will not have any effect on the ledger; that is,
    // the called chaincode on a different channel will not have its read set
    // and write set applied to the transaction. Only the calling chaincode's
    // read set and write set will be applied to the transaction. Effectively
    // the called chaincode on a different channel is a `Query`, which does not
    // participate in state validation checks in subsequent commit phase.
    // If `channel` is empty, the caller's channel is assumed.
    InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response

    // GetState returns the value of the specified `key` from the
    // ledger. Note that GetState doesn't read data from the writeset, which
    // has not been committed to the ledger. In other words, GetState doesn't
    // consider data modified by PutState that has not been committed.
    // If the key does not exist in the state database, (nil, nil) is returned.
    GetState(key string) ([]byte, error)

    // PutState puts the specified `key` and `value` into the transaction's
    // writeset as a data-write proposal. PutState doesn't effect the ledger
    // until the transaction is validated and successfully committed.
    // Simple keys must not be an empty string and must not start with null
    // character (0x00), in order to avoid range query collisions with
    // composite keys, which internally get prefixed with 0x00 as composite
    // key namespace.
    PutState(key string, value []byte) error

    // DelState records the specified `key` to be deleted in the writeset of
    // the transaction proposal. The `key` and its value will be deleted from
    // the ledger when the transaction is validated and successfully committed.
    DelState(key string) error

    // GetStateByRange returns a range iterator over a set of keys in the
    // ledger. The iterator can be used to iterate over all keys
    // between the startKey (inclusive) and endKey (exclusive).
    // The keys are returned by the iterator in lexical order. Note
    // that startKey and endKey can be empty string, which implies unbounded range
    // query on start or end.
    // Call Close() on the returned StateQueryIteratorInterface object when done.
    // The query is re-executed during validation phase to ensure result set
    // has not changed since transaction endorsement (phantom reads detected).
    GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error)

    // GetStateByPartialCompositeKey queries the state in the ledger based on
    // a given partial composite key. This function returns an iterator
    // which can be used to iterate over all composite keys whose prefix matches
    // the given partial composite key. The `objectType` and attributes are
    // expected to have only valid utf8 strings and should not contain
    // U+0000 (nil byte) and U+10FFFF (biggest and unallocated code point).
    // See related functions SplitCompositeKey and CreateCompositeKey.
    // Call Close() on the returned StateQueryIteratorInterface object when done.
    // The query is re-executed during validation phase to ensure result set
    // has not changed since transaction endorsement (phantom reads detected).
    GetStateByPartialCompositeKey(objectType string, keys []string) (StateQueryIteratorInterface, error)

    // CreateCompositeKey combines the given `attributes` to form a composite
    // key. The objectType and attributes are expected to have only valid utf8
    // strings and should not contain U+0000 (nil byte) and U+10FFFF
    // (biggest and unallocated code point).
    // The resulting composite key can be used as the key in PutState().
    CreateCompositeKey(objectType string, attributes []string) (string, error)

    // SplitCompositeKey splits the specified key into attributes on which the
    // composite key was formed. Composite keys found during range queries
    // or partial composite key queries can therefore be split into their
    // composite parts.
    SplitCompositeKey(compositeKey string) (string, []string, error)

    // GetQueryResult performs a "rich" query against a state database. It is
    // only supported for state databases that support rich query,
    // e.g.CouchDB. The query string is in the native syntax
    // of the underlying state database. An iterator is returned
    // which can be used to iterate (next) over the query result set.
    // The query is NOT re-executed during validation phase, phantom reads are
    // not detected. That is, other committed transactions may have added,
    // updated, or removed keys that impact the result set, and this would not
    // be detected at validation/commit time.  Applications susceptible to this
    // should therefore not use GetQueryResult as part of transactions that update
    // ledger, and should limit use to read-only chaincode operations.
    GetQueryResult(query string) (StateQueryIteratorInterface, error)

    // GetHistoryForKey returns a history of key values across time.
    // For each historic key update, the historic value and associated
    // transaction id and timestamp are returned. The timestamp is the
    // timestamp provided by the client in the proposal header.
    // GetHistoryForKey requires peer configuration
    // core.ledger.history.enableHistoryDatabase to be true.
    // The query is NOT re-executed during validation phase, phantom reads are
    // not detected. That is, other committed transactions may have updated
    // the key concurrently, impacting the result set, and this would not be
    // detected at validation/commit time. Applications susceptible to this
    // should therefore not use GetHistoryForKey as part of transactions that
    // update ledger, and should limit use to read-only chaincode operations.
    GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)

    // GetPrivateData returns the value of the specified `key` from the specified
    // `collection`. Note that GetPrivateData doesn't read data from the
    // private writeset, which has not been committed to the `collection`. In
    // other words, GetPrivateData doesn't consider data modified by PutPrivateData
    // that has not been committed.
    GetPrivateData(collection, key string) ([]byte, error)

    // PutPrivateData puts the specified `key` and `value` into the transaction's
    // private writeset. Note that only hash of the private writeset goes into the
    // transaction proposal response (which is sent to the client who issued the
    // transaction) and the actual private writeset gets temporarily stored in a
    // transient store. PutPrivateData doesn't effect the `collection` until the
    // transaction is validated and successfully committed. Simple keys must not be
    // an empty string and must not start with null character (0x00), in order to
    // avoid range query collisions with composite keys, which internally get
    // prefixed with 0x00 as composite key namespace.
    PutPrivateData(collection string, key string, value []byte) error

    // DelState records the specified `key` to be deleted in the private writeset of
    // the transaction. Note that only hash of the private writeset goes into the
    // transaction proposal response (which is sent to the client who issued the
    // transaction) and the actual private writeset gets temporarily stored in a
    // transient store. The `key` and its value will be deleted from the collection
    // when the transaction is validated and successfully committed.
    DelPrivateData(collection, key string) error

    // GetPrivateDataByRange returns a range iterator over a set of keys in a
    // given private collection. The iterator can be used to iterate over all keys
    // between the startKey (inclusive) and endKey (exclusive).
    // The keys are returned by the iterator in lexical order. Note
    // that startKey and endKey can be empty string, which implies unbounded range
    // query on start or end.
    // Call Close() on the returned StateQueryIteratorInterface object when done.
    // The query is re-executed during validation phase to ensure result set
    // has not changed since transaction endorsement (phantom reads detected).
    GetPrivateDataByRange(collection, startKey, endKey string) (StateQueryIteratorInterface, error)

    // GetPrivateDataByPartialCompositeKey queries the state in a given private
    // collection based on a given partial composite key. This function returns
    // an iterator which can be used to iterate over all composite keys whose prefix
    // matches the given partial composite key. The `objectType` and attributes are
    // expected to have only valid utf8 strings and should not contain
    // U+0000 (nil byte) and U+10FFFF (biggest and unallocated code point).
    // See related functions SplitCompositeKey and CreateCompositeKey.
    // Call Close() on the returned StateQueryIteratorInterface object when done.
    // The query is re-executed during validation phase to ensure result set
    // has not changed since transaction endorsement (phantom reads detected).
    GetPrivateDataByPartialCompositeKey(collection, objectType string, keys []string) (StateQueryIteratorInterface, error)

    // GetPrivateDataQueryResult performs a "rich" query against a given private
    // collection. It is only supported for state databases that support rich query,
    // e.g.CouchDB. The query string is in the native syntax
    // of the underlying state database. An iterator is returned
    // which can be used to iterate (next) over the query result set.
    // The query is NOT re-executed during validation phase, phantom reads are
    // not detected. That is, other committed transactions may have added,
    // updated, or removed keys that impact the result set, and this would not
    // be detected at validation/commit time.  Applications susceptible to this
    // should therefore not use GetQueryResult as part of transactions that update
    // ledger, and should limit use to read-only chaincode operations.
    GetPrivateDataQueryResult(collection, query string) (StateQueryIteratorInterface, error)

    // GetCreator returns `SignatureHeader.Creator` (e.g. an identity)
    // of the `SignedProposal`. This is the identity of the agent (or user)
    // submitting the transaction.
    GetCreator() ([]byte, error)

    // GetTransient returns the `ChaincodeProposalPayload.Transient` field.
    // It is a map that contains data (e.g. cryptographic material)
    // that might be used to implement some form of application-level
    // confidentiality. The contents of this field, as prescribed by
    // `ChaincodeProposalPayload`, are supposed to always
    // be omitted from the transaction and excluded from the ledger.
    GetTransient() (map[string][]byte, error)

    // GetBinding returns the transaction binding, which is used to enforce a
    // link between application data (like those stored in the transient field
    // above) to the proposal itself. This is useful to avoid possible replay
    // attacks.
    GetBinding() ([]byte, error)

    // GetDecorations returns additional data (if applicable) about the proposal
    // that originated from the peer. This data is set by the decorators of the
    // peer, which append or mutate the chaincode input passed to the chaincode.
    GetDecorations() map[string][]byte

    // GetSignedProposal returns the SignedProposal object, which contains all
    // data elements part of a transaction proposal.
    GetSignedProposal() (*pb.SignedProposal, error)

    // GetTxTimestamp returns the timestamp when the transaction was created. This
    // is taken from the transaction ChannelHeader, therefore it will indicate the
    // client's timestamp and will have the same value across all endorsers.
    GetTxTimestamp() (*timestamp.Timestamp, error)

    // SetEvent allows the chaincode to set an event on the response to the
    // proposal to be included as part of a transaction. The event will be
    // available within the transaction in the committed block regardless of the
    // validity of the transaction.
    SetEvent(name string, payload []byte) error
}

猜你喜欢

转载自blog.csdn.net/weixin_41926234/article/details/80982699