org.hyperledger.fabric.shim.ChaincodeStub Maven / Gradle / Ivy
Show all versions of fabric-chaincode-shim Show documentation
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.shim;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.hyperledger.fabric.protos.peer.ChaincodeEventPackage.ChaincodeEvent;
import org.hyperledger.fabric.protos.peer.ProposalPackage.SignedProposal;
import org.hyperledger.fabric.shim.Chaincode.Response;
import org.hyperledger.fabric.shim.ledger.CompositeKey;
import org.hyperledger.fabric.shim.ledger.KeyModification;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;
import org.hyperledger.fabric.shim.ledger.QueryResultsIteratorWithMetadata;
public interface ChaincodeStub {
/**
* Returns the arguments corresponding to the call to
* {@link Chaincode#init(ChaincodeStub)} or
* {@link Chaincode#invoke(ChaincodeStub)}, each argument represented as byte array.
*
* @return a list of arguments (bytes arrays)
*/
List getArgs();
/**
* Returns the arguments corresponding to the call to
* {@link Chaincode#init(ChaincodeStub)} or
* {@link Chaincode#invoke(ChaincodeStub)}, cast to UTF-8 string.
*
* @return a list of arguments cast to UTF-8 strings
*/
List getStringArgs();
/**
* A convenience method that returns the first argument of the chaincode
* invocation for use as a function name.
*
* The bytes of the first argument are decoded as a UTF-8 string.
*
* @return the function name
*/
String getFunction();
/**
* A convenience method that returns all except the first argument of the
* chaincode invocation for use as the parameters to the function returned
* by #{@link ChaincodeStub#getFunction()}.
*
* The bytes of the arguments are decoded as a UTF-8 strings and returned as
* a list of string parameters.
*
* @return a list of parameters
*/
List getParameters();
/**
* Returns the transaction id for the current chaincode invocation request.
*
* The transaction id uniquely identifies the transaction within the scope of the channel.
*
* @return the transaction id
*/
String getTxId();
/**
* Returns the channel id for the current proposal.
*
* This would be the 'channel_id' of the transaction proposal
* except where the chaincode is calling another on a different channel.
*
* @return the channel id
*/
String getChannelId();
/**
* Locally calls the specified chaincode invoke()
using the
* same transaction context.
*
* 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.
*
* Invoke another chaincode using the same transaction context.
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @param channel If not specified, the caller's channel is assumed.
* @return {@link Response} object returned by called chaincode
*/
Response invokeChaincode(String chaincodeName, List args, String channel);
/**
* 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.
*
* @param key name of the value
* @return value the value read from the ledger
*/
byte[] getState(String key);
/**
* retrieves the key-level endorsement policy for key
.
* Note that this will introduce a read dependency on key
in the transaction's readset.
* @param key key to get key level endorsement
* @return endorsement policy
*/
byte[] getStateValidationParameter(String key);
/**
* 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 0x00
* character, in order to avoid range query collisions with
* composite keys
*
* @param key name of the value
* @param value the value to write to the ledger
*/
void putState(String key, byte[] value);
/**
* Sets the key-level endorsement policy for key
.
*
* @param key key to set key level endorsement
* @param value endorsement policy
*/
void setStateValidationParameter(String key, byte[] value);
/**
* 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.
*
* @param key name of the value to be deleted
*/
void delState(String key);
/**
* Returns all existing keys, and their values, that are lexicographically
* between startkey
(inclusive) and the 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 {@link QueryResultsIterator#close()} object when done.
*
* @param startKey key as the start of the key range (inclusive)
* @param endKey key as the end of the key range (exclusive)
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getStateByRange(String startKey, String endKey);
/**
* Returns a range iterator over a set of keys in the ledger. The iterator can be used to fetch keys between the
* startKey
(inclusive) and endKey
(exclusive).
* When an empty string is passed as a value to the bookmark
argument, the returned iterator can be used to fetch
* the first pageSize
keys between the startKey
and endKey
.
* When the bookmark
is a non-empty string, the iterator can be used to fetch first pageSize
keys between the
* bookmark
and endKey
.
* Note that only the bookmark present in a prior page of query results ({@link org.hyperledger.fabric.protos.peer.ChaincodeShim.QueryResponseMetadata})
* can be used as a value to the bookmark argument. Otherwise, an empty string must be passed as bookmark.
* 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.
* This call is only supported in a read only transaction.
*
* @param startKey
* @param endKey
* @param pageSize
* @param bookmark
* @return QueryIterator
*/
QueryResultsIteratorWithMetadata getStateByRangeWithPagination(String startKey, String endKey, int pageSize, String bookmark);
/**
* Returns all existing keys, and their values, that are prefixed by the
* specified partial {@link CompositeKey}.
*
* If a full composite key is specified, it will not match itself, resulting
* in no keys being returned.
*
*
*
* This method takes responsibility to correctly parse the {@link CompositeKey} from a String
* and behaves exactly as {@link ChaincodeStub#getStateByPartialCompositeKey(CompositeKey)}.
*
*
* Call close() on the returned {@link QueryResultsIterator#close()} object when done.
*
* @param compositeKey partial composite key
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getStateByPartialCompositeKey(String compositeKey);
/**
* Returns all existing keys, and their values, that are prefixed by the
* specified partial {@link CompositeKey}.
*
* It combines the attributes and the objectType to form a partial composite key.
*
* If a full composite key is specified, it will not match itself, resulting
* in no keys being returned.
*
* This method takes responsibility to correctly combine Object type and attributes
* creating a {@link CompositeKey} and behaves exactly
* as {@link ChaincodeStub#getStateByPartialCompositeKey(CompositeKey)}.
*
* Call close() on the returned {@link QueryResultsIterator#close()} object when done.
*
* @param objectType ObjectType of the compositeKey
* @param attributes Attributes of the composite key
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getStateByPartialCompositeKey(String objectType, String... attributes);
/**
* Returns all existing keys, and their values, that are prefixed by the
* specified partial {@link CompositeKey}.
*
* If a full composite key is specified, it will not match itself, resulting
* in no keys being returned.
*
* @param compositeKey partial composite key
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getStateByPartialCompositeKey(CompositeKey compositeKey);
/**
* 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 the composite keys whose prefix matches the given partial composite key.
* When an empty string is passed as a value to the bookmark
argument, the returned iterator can be used to fetch
* the first pageSize
composite keys whose prefix matches the given partial composite key.
* When the bookmark
is a non-empty string, the iterator can be used to fetch first pageSize
keys between the
* bookmark
(inclusive) and and the last matching composite key.
* Note that only the bookmark present in a prior page of query results ({@link org.hyperledger.fabric.protos.peer.ChaincodeShim.QueryResponseMetadata})
* can be used as a value to the bookmark argument. Otherwise, an empty string must be passed as bookmark.
* This call is only supported in a read only transaction.
*
* @param compositeKey
* @param pageSize
* @param bookmark
* @return QueryIterator
*/
QueryResultsIteratorWithMetadata getStateByPartialCompositeKeyWithPagination(CompositeKey compositeKey, int pageSize, String bookmark);
/**
* Given a set of attributes, this method combines these attributes to
* return a composite key.
*
* @param objectType A string used as the prefix of the resulting key
* @param attributes List of attribute values to concatenate into the key
* @return a composite key
*/
CompositeKey createCompositeKey(String objectType, String... attributes);
/**
* Parses a composite key {@link CompositeKey} from a string.
*
* @param compositeKey a composite key string
* @return a composite key
*/
CompositeKey splitCompositeKey(String compositeKey);
/**
* 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 {@link QueryResultsIterator} is returned
* which can be used to iterate (next) over the query result set.
*
* @param query query string in a syntax supported by the underlying state
* database
* @return {@link QueryResultsIterator} object contains query results
* @throws UnsupportedOperationException if the underlying state database does not support rich
* queries.
*/
QueryResultsIterator getQueryResult(String query);
/**
* 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 over keys in the query result set.
* When an empty string is passed as a value to the bookmark
argument, the returned iterator can be used to fetch
* the first pageSize
of query results..
* When the bookmark
is a non-empty string, the iterator can be used to fetch first pageSize
keys between the
* bookmark
(inclusive) and the last key in the query result.
* Note that only the bookmark present in a prior page of query results ({@link org.hyperledger.fabric.protos.peer.ChaincodeShim.QueryResponseMetadata})
* can be used as a value to the bookmark argument. Otherwise, an empty string must be passed as bookmark.
* This call is only supported in a read only transaction.
*
* @param query
* @param pageSize
* @param bookmark
* @return QueryIterator
*/
QueryResultsIteratorWithMetadata getQueryResultWithPagination(String query, int pageSize, String bookmark);
/**
* 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.
* This method requires peer configuration
* core.ledger.history.enableHistoryDatabase
to be true.
*
* @param key The state variable key
* @return an {@link Iterable} of {@link KeyModification}
*/
QueryResultsIterator getHistoryForKey(String key);
/**
* Returns the value of the specified key
from the specified
* collection
.
*
* Note that {@link #getPrivateData(String, String)} doesn't read data from the
* private writeset, which has not been committed to the collection
. In
* other words, {@link #getPrivateData(String, String)} doesn't consider data modified by {@link #putPrivateData(String, String, byte[])} * that has not been committed.
*
* @param collection name of the collection
* @param key name of the value
* @return value the value read from the collection
*/
byte[] getPrivateData(String collection, String key);
/**
* @param collection name of the collection
* @param key name of the value
* @return
*/
byte[] getPrivateDataHash(String collection, String key);
/**
* Retrieves the key-level endorsement
* policy for the private data specified by key
. Note that this introduces
* a read dependency on key
in the transaction's readset.
*
* @param collection name of the collection
* @param key key to get endorsement policy
* @return Key Level endorsement as byte array
*/
byte[] getPrivateDataValidationParameter(String collection, String key);
/**
* 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.
*
* @param collection name of the collection
* @param key name of the value
* @param value the value to write to the ledger
*/
void putPrivateData(String collection, String key, byte[] value);
/**
* Sets the key-level endorsement policy for the private data specified by key
.
*
* @param collection name of the collection
* @param key key to set endorsement policy
* @param value endorsement policy
*/
void setPrivateDataValidationParameter(String collection, String key, byte[] value);
/**
* 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.
*
* @param collection name of the collection
* @param key name of the value to be deleted
*/
void delPrivateData(String collection, String key);
/**
* Returns all existing keys, and their values, that are lexicographically
* between startkey
(inclusive) and the endKey
* (exclusive) in a given private collection.
*
* Note that startKey and endKey can be empty string, which implies unbounded range
* query on start or end.
* The query is re-executed during validation phase to ensure result set
* has not changed since transaction endorsement (phantom reads detected).
*
* @param collection name of the collection
* @param startKey private data variable key as the start of the key range (inclusive)
* @param endKey private data variable key as the end of the key range (exclusive)
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getPrivateDataByRange(String collection, String startKey, String endKey);
/**
* Returns all existing keys, and their values, that are prefixed by the
* specified partial {@link CompositeKey} in a given private collection.
*
* If a full composite key is specified, it will not match itself, resulting
* in no keys being returned.
*
* The query is re-executed during validation phase to ensure result set
* has not changed since transaction endorsement (phantom reads detected).
*
* This method takes responsibility to correctly parse the {@link CompositeKey} from a String
* and behaves exactly as {@link ChaincodeStub#getPrivateDataByPartialCompositeKey(String, CompositeKey)}.
*
*
* @param collection name of the collection
* @param compositeKey partial composite key
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getPrivateDataByPartialCompositeKey(String collection, String compositeKey);
/**
* Returns all existing keys, and their values, that are prefixed by the
* specified partial {@link CompositeKey} in a given private collection.
*
* If a full composite key is specified, it will not match itself, resulting
* in no keys being returned.
*
* The query is re-executed during validation phase to ensure result set
* has not changed since transaction endorsement (phantom reads detected).
*
* @param collection name of the collection
* @param compositeKey partial composite key
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getPrivateDataByPartialCompositeKey(String collection, CompositeKey compositeKey);
/**
* Returns all existing keys, and their values, that are prefixed by the
* specified partial {@link CompositeKey} in a given private collection.
*
* If a full composite key is specified, it will not match itself, resulting
* in no keys being returned.
*
* The query is re-executed during validation phase to ensure result set
* has not changed since transaction endorsement (phantom reads detected).
*
* This method takes responsibility to correctly combine Object type and attributes
* creating a {@link CompositeKey} and behaves exactly
* as {@link ChaincodeStub#getPrivateDataByPartialCompositeKey(String, CompositeKey)}.
*
*
* @param collection name of the collection
* @param objectType ObjectType of the compositeKey
* @param attributes Attributes of the composite key
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator getPrivateDataByPartialCompositeKey(String collection, String objectType, String... attributes);
/**
* Perform 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.
*
* @param collection name of the collection
* @param query query string in a syntax supported by the underlying state
* database
* @return {@link QueryResultsIterator} object contains query results
* @throws UnsupportedOperationException if the underlying state database does not support rich
* queries.
*/
QueryResultsIterator getPrivateDataQueryResult(String collection, String query);
/**
* Defines the CHAINCODE type event that will be posted to interested
* clients when the chaincode's result is committed to the ledger.
*
* @param name Name of event. Cannot be null or empty string.
* @param payload Optional event payload.
*/
void setEvent(String name, byte[] payload);
/**
* Invoke another chaincode using the same transaction context.
*
* Same as {@link #invokeChaincode(String, List, String)}
* using channelId to null
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @return {@link Response} object returned by called chaincode
*/
default Response invokeChaincode(String chaincodeName, List args) {
return invokeChaincode(chaincodeName, args, null);
}
/**
* Invoke another chaincode using the same transaction context.
*
* This is a convenience version of
* {@link #invokeChaincode(String, List, String)}. The string args will be
* encoded into as UTF-8 bytes.
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @param channel If not specified, the caller's channel is assumed.
* @return {@link Response} object returned by called chaincode
*/
default Response invokeChaincodeWithStringArgs(String chaincodeName, List args, String channel) {
return invokeChaincode(chaincodeName, args.stream().map(x -> x.getBytes(UTF_8)).collect(toList()), channel);
}
/**
* Invoke another chaincode using the same transaction context.
*
* This is a convenience version of {@link #invokeChaincode(String, List)}.
* The string args will be encoded into as UTF-8 bytes.
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @return {@link Response} object returned by called chaincode
*/
default Response invokeChaincodeWithStringArgs(String chaincodeName, List args) {
return invokeChaincodeWithStringArgs(chaincodeName, args, null);
}
/**
* Invoke another chaincode using the same transaction context.
*
* This is a convenience version of {@link #invokeChaincode(String, List)}.
* The string args will be encoded into as UTF-8 bytes.
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @return {@link Response} object returned by called chaincode
*/
default Response invokeChaincodeWithStringArgs(final String chaincodeName, final String... args) {
return invokeChaincodeWithStringArgs(chaincodeName, Arrays.asList(args), null);
}
/**
* Returns the byte array value specified by the key and decoded as a UTF-8
* encoded string, from the ledger.
*
* This is a convenience version of {@link #getState(String)}
*
* @param key name of the value
* @return value the value read from the ledger
*/
default String getStringState(String key) {
return new String(getState(key), UTF_8);
}
/**
* Writes the specified value and key into the sidedb collection
* value converted to byte array.
*
* @param collection collection name
* @param key name of the value
* @param value the value to write to the ledger
*/
default void putPrivateData(String collection, String key, String value) {
putPrivateData(collection, key, value.getBytes(UTF_8));
}
/**
* Returns the byte array value specified by the key and decoded as a UTF-8
* encoded string, from the sidedb collection.
*
* @param collection collection name
* @param key name of the value
* @return value the value read from the ledger
*/
default String getPrivateDataUTF8(String collection, String key) {
return new String(getPrivateData(collection, key), UTF_8);
}
/**
* Writes the specified value and key into the ledger
*
* @param key name of the value
* @param value the value to write to the ledger
*/
default void putStringState(String key, String value) {
putState(key, value.getBytes(UTF_8));
}
/**
* Returns the CHAINCODE type event that will be posted to interested
* clients when the chaincode's result is committed to the ledger.
*
* @return the chaincode event or null
*/
ChaincodeEvent getEvent();
/**
* Returns the signed transaction proposal currently being executed.
*
* @return null if the current transaction is an internal call to a system
* chaincode.
*/
SignedProposal getSignedProposal();
/**
* Returns the timestamp when the transaction was created.
*
* @return timestamp as specified in the transaction's channel header.
*/
Instant getTxTimestamp();
/**
* Returns the identity of the agent (or user) submitting the transaction.
*
* @return the bytes of the creator field of the proposal's signature
* header.
*/
byte[] getCreator();
/**
* Returns the transient map associated with the current transaction.
*
* @return map of transient field
*/
Map getTransient();
/**
* Returns the transaction binding.
*
* @return binding between application data and proposal
*/
byte[] getBinding();
}