All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hyperledger.fabric.shim.ChaincodeStub Maven / Gradle / Ivy

The newest version!
/*
 * 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(); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy