
org.hyperledger.fabric.shim.ChaincodeStub Maven / Gradle / Ivy
Show all versions of fabric-chaincode-shim Show documentation
/*
* Copyright 2019 IBM 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.ChaincodeEvent;
import org.hyperledger.fabric.protos.peer.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;
/**
* An object which manages the transaction context, provides access to state variables, and supports calls to other
* chaincode implementations.
*/
@SuppressWarnings("PMD.ExcessivePublicCount")
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.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 the start key
* @param endKey the end key
* @param pageSize the page size
* @param bookmark the 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.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 the composite key
* @param pageSize the page size
* @param bookmark the 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.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 the query
* @param pageSize the page size
* @param bookmark the 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 the private data hash
*/
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);
/**
* Reqauests purging of the specified key
to be from the private data stores.
*
*
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 purged from the collection. This is an asynchronous activity.
*
*
Purge is a complete removal of the history of the key. There is existing purge possible mased on block height.
* This API allows the contract to be pro-active in requesting data be purged. This can contribute towards meeting
* privacy requirements.
*
* @param collection name of the collection
* @param key name of the value to be deleted
*/
void purgePrivateData(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);
/**
* Allows the chaincode to propose an event on the transaction proposal response. When the transaction is included
* in a block and the block is successfully committed to the ledger, the block event (including transaction level
* chaincode events) will be delivered to the current client application event listeners that have been registered
* with the peer's event producer. Consult each SDK's documentation for details. Only a single chaincode event can
* be included in a transaction. If setEvent() is called multiple times only the last event will be included in the
* transaction. The event must originate from the outer-most invoked chaincode in chaincode-to-chaincode scenarios.
* The marshaled ChaincodeEvent will be available in the transaction's ChaincodeAction.events field.
*
* @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(final String chaincodeName, final 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(
final String chaincodeName, final List args, final 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(final String chaincodeName, final 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(final 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(final String collection, final String key, final 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(final String collection, final 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(final String key, final 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();
/**
* Get the MSPID of the peer that started this chaincode.
*
* @return string MSPID
*/
String getMspId();
}