Repository: hyperledger/fabric-chaincode-java
Branch: main
Commit: 5cd4f4588b58
Files: 334
Total size: 953.0 KB
Directory structure:
gitextract_fa6p6lwj/
├── .github/
│ ├── dependabot.yml
│ ├── settings.yml
│ └── workflows/
│ ├── pull_request.yml
│ ├── push.yml
│ ├── release.yml
│ ├── scan.yml
│ ├── schedule.yml
│ ├── scheduled-scan.yml
│ └── test.yml
├── .gitignore
├── CHANGELOG.md
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── COMPATIBILITY.md
├── CONTRIBUTING.md
├── LICENSE
├── MAINTAINERS.md
├── Makefile
├── README.md
├── RELEASING.md
├── SECURITY.md
├── build.gradle
├── docs/
│ ├── 404.md
│ ├── _config.yml
│ ├── _includes/
│ │ ├── footer.html
│ │ ├── header.html
│ │ └── javadocs.html
│ └── index.md
├── examples/
│ ├── fabric-contract-example-as-service/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── example/
│ │ │ └── contract/
│ │ │ ├── MyAsset.java
│ │ │ └── MyAssetContract.java
│ │ └── test/
│ │ └── java/
│ │ └── org/
│ │ └── example/
│ │ └── MyAssetContractTest.java
│ ├── fabric-contract-example-gradle/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── build.gradle
│ │ └── src/
│ │ ├── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── example/
│ │ │ ├── MyAsset.java
│ │ │ └── MyAssetContract.java
│ │ └── test/
│ │ └── java/
│ │ └── org/
│ │ └── example/
│ │ └── MyAssetContractTest.java
│ ├── fabric-contract-example-gradle-kotlin/
│ │ ├── .fabricignore
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── settings.gradle.kts
│ │ └── src/
│ │ ├── main/
│ │ │ └── kotlin/
│ │ │ └── org/
│ │ │ └── example/
│ │ │ ├── MyAsset.kt
│ │ │ └── MyAssetContract.kt
│ │ └── test/
│ │ └── kotlin/
│ │ └── org/
│ │ └── example/
│ │ └── MyAssetContractTest.kt
│ ├── fabric-contract-example-maven/
│ │ ├── .gitignore
│ │ ├── pom.xml
│ │ └── src/
│ │ ├── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── example/
│ │ │ ├── MyAsset.java
│ │ │ └── MyAssetContract.java
│ │ └── test/
│ │ └── java/
│ │ └── org/
│ │ └── example/
│ │ └── MyAssetContractTest.java
│ └── ledger-api/
│ ├── .gitignore
│ ├── README.md
│ ├── build.gradle
│ └── src/
│ └── main/
│ └── java/
│ └── org/
│ └── example/
│ ├── LedgerAPIContract.java
│ └── MyAsset.java
├── fabric-chaincode-docker/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── README.md
│ ├── build.gradle
│ ├── build.sh
│ └── start
├── fabric-chaincode-integration-test/
│ ├── .gitignore
│ ├── build.gradle
│ ├── chaincodebootstrap.gradle
│ └── src/
│ ├── contracts/
│ │ ├── bare-gradle/
│ │ │ ├── build.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── hyperledger/
│ │ │ │ └── fabric/
│ │ │ │ └── example/
│ │ │ │ └── BareGradle.java
│ │ │ └── resources/
│ │ │ └── config.props
│ │ ├── bare-maven/
│ │ │ ├── .gitignore
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── hyperledger/
│ │ │ │ └── fabric/
│ │ │ │ └── example/
│ │ │ │ └── BareMaven.java
│ │ │ └── resources/
│ │ │ └── config.props
│ │ ├── fabric-ledger-api/
│ │ │ ├── build.gradle
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── hyperledger/
│ │ │ └── fabric/
│ │ │ └── example/
│ │ │ └── AllLedgerAPI.java
│ │ ├── fabric-shim-api/
│ │ │ ├── build.gradle
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── settings.gradle
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── hyperledger/
│ │ │ │ └── fabric/
│ │ │ │ └── example/
│ │ │ │ ├── AllAPI.java
│ │ │ │ └── EndorsementCC.java
│ │ │ └── resources/
│ │ │ └── config.props
│ │ └── wrapper-maven/
│ │ ├── .gitignore
│ │ ├── .mvn/
│ │ │ └── wrapper/
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ │ ├── mvnw
│ │ ├── mvnw.cmd
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── hyperledger/
│ │ │ └── fabric/
│ │ │ └── example/
│ │ │ └── WrapperMaven.java
│ │ └── resources/
│ │ └── config.props
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── hyperleder/
│ │ └── fabric/
│ │ └── shim/
│ │ └── integration/
│ │ ├── contractinstall/
│ │ │ └── ContractInstallTest.java
│ │ ├── ledgertests/
│ │ │ └── LedgerIntegrationTest.java
│ │ ├── shimtests/
│ │ │ ├── SACCIntegrationTest.java
│ │ │ └── SBECCIntegrationTest.java
│ │ └── util/
│ │ ├── Bash.java
│ │ ├── Command.java
│ │ ├── Docker.java
│ │ ├── DockerCompose.java
│ │ ├── FabricState.java
│ │ ├── InvokeHelper.java
│ │ └── Peer.java
│ └── resources/
│ ├── docker-compose-microfab.yaml
│ └── scripts/
│ ├── ccutils.sh
│ ├── collection_config.json
│ └── mfsetup.sh
├── fabric-chaincode-shim/
│ ├── build.gradle
│ ├── javabuild.sh
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── hyperledger/
│ │ │ └── fabric/
│ │ │ ├── Logger.java
│ │ │ ├── Logging.java
│ │ │ ├── contract/
│ │ │ │ ├── ClientIdentity.java
│ │ │ │ ├── Context.java
│ │ │ │ ├── ContextFactory.java
│ │ │ │ ├── ContractInterface.java
│ │ │ │ ├── ContractRouter.java
│ │ │ │ ├── ContractRuntimeException.java
│ │ │ │ ├── annotation/
│ │ │ │ │ ├── Contact.java
│ │ │ │ │ ├── Contract.java
│ │ │ │ │ ├── DataType.java
│ │ │ │ │ ├── Default.java
│ │ │ │ │ ├── Info.java
│ │ │ │ │ ├── License.java
│ │ │ │ │ ├── Property.java
│ │ │ │ │ ├── Serializer.java
│ │ │ │ │ ├── Transaction.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── execution/
│ │ │ │ │ ├── ExecutionFactory.java
│ │ │ │ │ ├── ExecutionService.java
│ │ │ │ │ ├── InvocationRequest.java
│ │ │ │ │ ├── JSONTransactionSerializer.java
│ │ │ │ │ ├── SerializerInterface.java
│ │ │ │ │ ├── impl/
│ │ │ │ │ │ ├── ContractExecutionService.java
│ │ │ │ │ │ ├── ContractInvocationRequest.java
│ │ │ │ │ │ └── package-info.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── metadata/
│ │ │ │ │ ├── MetadataBuilder.java
│ │ │ │ │ ├── TypeSchema.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── package-info.java
│ │ │ │ ├── routing/
│ │ │ │ │ ├── ContractDefinition.java
│ │ │ │ │ ├── DataTypeDefinition.java
│ │ │ │ │ ├── ParameterDefinition.java
│ │ │ │ │ ├── PropertyDefinition.java
│ │ │ │ │ ├── RoutingRegistry.java
│ │ │ │ │ ├── TransactionType.java
│ │ │ │ │ ├── TxFunction.java
│ │ │ │ │ ├── TypeRegistry.java
│ │ │ │ │ ├── impl/
│ │ │ │ │ │ ├── ContractDefinitionImpl.java
│ │ │ │ │ │ ├── DataTypeDefinitionImpl.java
│ │ │ │ │ │ ├── ParameterDefinitionImpl.java
│ │ │ │ │ │ ├── PropertyDefinitionImpl.java
│ │ │ │ │ │ ├── RoutingRegistryImpl.java
│ │ │ │ │ │ ├── SerializerRegistryImpl.java
│ │ │ │ │ │ ├── TxFunctionImpl.java
│ │ │ │ │ │ ├── TypeRegistryImpl.java
│ │ │ │ │ │ └── package-info.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── systemcontract/
│ │ │ │ ├── SystemContract.java
│ │ │ │ └── package-info.java
│ │ │ ├── ledger/
│ │ │ │ ├── Collection.java
│ │ │ │ ├── Ledger.java
│ │ │ │ ├── impl/
│ │ │ │ │ ├── LedgerImpl.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── package-info.java
│ │ │ ├── metrics/
│ │ │ │ ├── Metrics.java
│ │ │ │ ├── MetricsProvider.java
│ │ │ │ ├── TaskMetricsCollector.java
│ │ │ │ ├── impl/
│ │ │ │ │ ├── DefaultProvider.java
│ │ │ │ │ ├── NullProvider.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── package-info.java
│ │ │ ├── overview.html
│ │ │ ├── package-info.java
│ │ │ ├── shim/
│ │ │ │ ├── Chaincode.java
│ │ │ │ ├── ChaincodeBase.java
│ │ │ │ ├── ChaincodeException.java
│ │ │ │ ├── ChaincodeServer.java
│ │ │ │ ├── ChaincodeServerProperties.java
│ │ │ │ ├── ChaincodeStub.java
│ │ │ │ ├── ChatChaincodeWithPeer.java
│ │ │ │ ├── GrpcServer.java
│ │ │ │ ├── NettyChaincodeServer.java
│ │ │ │ ├── NettyGrpcServer.java
│ │ │ │ ├── ResponseUtils.java
│ │ │ │ ├── ext/
│ │ │ │ │ └── sbe/
│ │ │ │ │ ├── StateBasedEndorsement.java
│ │ │ │ │ ├── impl/
│ │ │ │ │ │ ├── StateBasedEndorsementFactory.java
│ │ │ │ │ │ ├── StateBasedEndorsementImpl.java
│ │ │ │ │ │ ├── StateBasedEndorsementUtils.java
│ │ │ │ │ │ └── package-info.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── impl/
│ │ │ │ │ ├── ChaincodeInvocationTask.java
│ │ │ │ │ ├── ChaincodeMessageFactory.java
│ │ │ │ │ ├── ChaincodeSupportClient.java
│ │ │ │ │ ├── InvocationStubImpl.java
│ │ │ │ │ ├── InvocationTaskExecutor.java
│ │ │ │ │ ├── InvocationTaskManager.java
│ │ │ │ │ ├── KeyModificationImpl.java
│ │ │ │ │ ├── KeyValueImpl.java
│ │ │ │ │ ├── QueryResultsIteratorImpl.java
│ │ │ │ │ ├── QueryResultsIteratorWithMetadataImpl.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── ledger/
│ │ │ │ │ ├── CompositeKey.java
│ │ │ │ │ ├── CompositeKeyFormatException.java
│ │ │ │ │ ├── KeyModification.java
│ │ │ │ │ ├── KeyValue.java
│ │ │ │ │ ├── QueryResultsIterator.java
│ │ │ │ │ ├── QueryResultsIteratorWithMetadata.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── package-info.java
│ │ │ └── traces/
│ │ │ ├── Traces.java
│ │ │ ├── TracesProvider.java
│ │ │ ├── impl/
│ │ │ │ ├── DefaultTracesProvider.java
│ │ │ │ ├── NullProvider.java
│ │ │ │ ├── OpenTelemetryProperties.java
│ │ │ │ ├── OpenTelemetryTracesProvider.java
│ │ │ │ └── package-info.java
│ │ │ └── package-info.java
│ │ └── resources/
│ │ ├── contract-schema.json
│ │ └── json-schema-draft-04-schema.json
│ └── test/
│ ├── java/
│ │ ├── ChaincodeWithoutPackageTest.java
│ │ ├── EmptyChaincodeWithoutPackage.java
│ │ ├── contract/
│ │ │ ├── Greeting.java
│ │ │ └── SampleContract.java
│ │ └── org/
│ │ └── hyperledger/
│ │ └── fabric/
│ │ ├── LoggerTest.java
│ │ ├── LoggingTest.java
│ │ ├── TestUtil.java
│ │ ├── contract/
│ │ │ ├── AllTypesAsset.java
│ │ │ ├── ChaincodeStubNaiveImpl.java
│ │ │ ├── ClientIdentityTest.java
│ │ │ ├── ContextFactoryTest.java
│ │ │ ├── ContextTest.java
│ │ │ ├── ContractInterfaceTest.java
│ │ │ ├── ContractRouterTest.java
│ │ │ ├── MyType.java
│ │ │ ├── MyType2.java
│ │ │ ├── TransactionExceptionTest.java
│ │ │ ├── execution/
│ │ │ │ ├── ContractExecutionServiceTest.java
│ │ │ │ └── JSONTransactionSerializerTest.java
│ │ │ ├── metadata/
│ │ │ │ ├── MetadataBuilderTest.java
│ │ │ │ └── TypeSchemaTest.java
│ │ │ ├── routing/
│ │ │ │ ├── ContractDefinitionTest.java
│ │ │ │ ├── DataTypeDefinitionTest.java
│ │ │ │ ├── ParameterDefinitionTest.java
│ │ │ │ ├── PropertyDefinitionTest.java
│ │ │ │ ├── TxFunctionTest.java
│ │ │ │ └── TypeRegistryTest.java
│ │ │ └── simplepath/
│ │ │ └── ContractSimplePathTest.java
│ │ ├── ledger/
│ │ │ └── LedgerTest.java
│ │ ├── metrics/
│ │ │ ├── MetricsTest.java
│ │ │ └── impl/
│ │ │ └── DefaultProviderTest.java
│ │ ├── shim/
│ │ │ ├── ChaincodeBaseTest.java
│ │ │ ├── ChaincodeServerImplTest.java
│ │ │ ├── ChaincodeStubTest.java
│ │ │ ├── ChaincodeTest.java
│ │ │ ├── ChatChaincodeWithPeerTest.java
│ │ │ ├── NettyGrpcServerTest.java
│ │ │ ├── chaincode/
│ │ │ │ └── EmptyChaincode.java
│ │ │ ├── ext/
│ │ │ │ └── sbe/
│ │ │ │ ├── StateBasedEndorsementTest.java
│ │ │ │ └── impl/
│ │ │ │ ├── StateBasedEndorsementFactoryTest.java
│ │ │ │ └── StateBasedEndorsementImplTest.java
│ │ │ ├── fvt/
│ │ │ │ └── ChaincodeFVTest.java
│ │ │ ├── impl/
│ │ │ │ ├── ChaincodeMessageFactoryTest.java
│ │ │ │ ├── ChaincodeSupportClientTest.java
│ │ │ │ ├── InnvocationTaskManagerTest.java
│ │ │ │ ├── InvocationStubImplTest.java
│ │ │ │ ├── InvocationTaskManagerTest.java
│ │ │ │ ├── KeyModificationImplTest.java
│ │ │ │ ├── KeyValueImplTest.java
│ │ │ │ └── QueryResultsIteratorWithMetadataImplTest.java
│ │ │ ├── ledger/
│ │ │ │ └── CompositeKeyTest.java
│ │ │ ├── mock/
│ │ │ │ └── peer/
│ │ │ │ ├── ChaincodeMockPeer.java
│ │ │ │ ├── CompleteStep.java
│ │ │ │ ├── DelValueStep.java
│ │ │ │ ├── ErrorResponseStep.java
│ │ │ │ ├── GetHistoryForKeyStep.java
│ │ │ │ ├── GetQueryResultStep.java
│ │ │ │ ├── GetStateByRangeStep.java
│ │ │ │ ├── GetStateMetadata.java
│ │ │ │ ├── GetValueStep.java
│ │ │ │ ├── InvokeChaincodeStep.java
│ │ │ │ ├── PurgeValueStep.java
│ │ │ │ ├── PutStateMetadata.java
│ │ │ │ ├── PutValueStep.java
│ │ │ │ ├── QueryCloseStep.java
│ │ │ │ ├── QueryNextStep.java
│ │ │ │ ├── QueryResultStep.java
│ │ │ │ ├── RegisterStep.java
│ │ │ │ └── ScenarioStep.java
│ │ │ └── utils/
│ │ │ ├── MessageUtil.java
│ │ │ └── TimeoutUtil.java
│ │ └── traces/
│ │ ├── TracesTest.java
│ │ └── impl/
│ │ ├── DefaultProviderTest.java
│ │ ├── OpenTelemetryPropertiesTest.java
│ │ ├── OpenTelemetryTracesProviderTest.java
│ │ └── TestSpanExporterProvider.java
│ └── resources/
│ ├── META-INF/
│ │ └── services/
│ │ └── io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider
│ ├── ca.crt
│ ├── client.crt
│ ├── client.crt.enc
│ ├── client.key
│ ├── client.key.enc
│ └── client.key.password-protected
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── pmd-ruleset.xml
├── release_notes/
│ ├── v1.3.0.txt
│ ├── v1.4.0.txt
│ ├── v2.0.0-alpha.txt
│ ├── v2.0.0-beta.txt
│ ├── v2.0.0.txt
│ ├── v2.0.1.txt
│ ├── v2.1.0.txt
│ ├── v2.1.1.txt
│ ├── v2.2.0.txt
│ ├── v2.2.1.txt
│ ├── v2.3.0.txt
│ ├── v2.3.1.txt
│ ├── v2.4.0-beta.txt
│ ├── v2.4.0.txt
│ ├── v2.4.1.txt
│ └── v2.5.0.txt
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/dependabot.yml
================================================
version: 2
multi-ecosystem-groups:
java:
schedule:
interval: daily
updates:
- package-ecosystem: docker
directories:
- "/fabric-chaincode-docker"
- "/examples/fabric-contract-example-as-service"
schedule:
interval: daily
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
- package-ecosystem: gradle
multi-ecosystem-group: java
patterns:
- "*"
directories:
- "/"
- "/fabric-chaincode-docker"
- "/examples/fabric-contract-example-as-service"
- "/examples/fabric-contract-example-gradle"
- "/examples/fabric-contract-example-gradle-kotlin"
- "/examples/ledger-api"
- "/fabric-chaincode-integration-test"
- "/fabric-chaincode-integration-test/src/contracts/bare-gradle"
- "/fabric-chaincode-integration-test/src/contracts/fabric-ledger-api"
- "/fabric-chaincode-integration-test/src/contracts/fabric-shim-api"
- "/fabric-chaincode-shim"
- package-ecosystem: maven
multi-ecosystem-group: java
patterns:
- "*"
directories:
- "/examples/fabric-contract-example-maven"
- "/fabric-chaincode-integration-test/src/contracts/bare-maven"
- "/fabric-chaincode-integration-test/src/contracts/wrapper-maven"
================================================
FILE: .github/settings.yml
================================================
#
# SPDX-License-Identifier: Apache-2.0
#
repository:
name: fabric-chaincode-java
description: Hyperledger Fabric Contract and Chaincode implementation for Java
https://wiki.hyperledger.org/display/fabric
homepage: https://jira.hyperledger.org/issues/?jql=project+%3D+FAB+AND+component+%3D+fabric-chaincode-java
default_branch: main
has_downloads: true
has_issues: false
has_projects: false
has_wiki: false
archived: false
private: false
allow_squash_merge: false
allow_merge_commit: true
allow_rebase_merge: true
================================================
FILE: .github/workflows/pull_request.yml
================================================
# Copyright the Hyperledger Fabric contributors. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: Pull request
on:
pull_request:
branches:
- main
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test:
uses: ./.github/workflows/test.yml
scan:
uses: ./.github/workflows/scan.yml
pull-request:
needs: test
name: Pull request success
runs-on: ubuntu-latest
steps:
- run: "true"
================================================
FILE: .github/workflows/push.yml
================================================
# Copyright the Hyperledger Fabric contributors. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: Push
on:
push:
branches:
- main
workflow_dispatch:
jobs:
test:
uses: ./.github/workflows/test.yml
================================================
FILE: .github/workflows/release.yml
================================================
# Copyright the Hyperledger Fabric contributors. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
name: Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+-*"
workflow_dispatch:
env:
IMAGE_NAME: ${{ github.repository_owner }}/fabric-javaenv
jobs:
publish-github:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: "temurin"
java-version: 25
- uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Publish to GitHub Packages
run: |
./gradlew publishAllPublicationsToGitHubRepository
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-maven:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: "temurin"
java-version: 25
- uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Publish to Maven Central
run: |
./gradlew publishAggregationToCentralPortal
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVENCENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVENCENTRAL_PASSWORD }}
docker-build-push:
name: Push Docker image
runs-on: ${{ matrix.arch.runner }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
arch:
- platform: linux-amd64
runner: ubuntu-24.04
- platform: linux-arm64
runner: ubuntu-24.04-arm
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: "temurin"
java-version: 25
- uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Build the dependencies needed for the image
run: ./gradlew :fabric-chaincode-docker:copyAllDeps
- name: Get commit timestamp
run: echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> "${GITHUB_ENV}"
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: docker.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Build image
id: build
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
file: fabric-chaincode-docker/Dockerfile
context: fabric-chaincode-docker
outputs: type=registry,"name=${{ format('ghcr.io/{0},docker.io/{0}', env.IMAGE_NAME) }}",push-by-digest=true,name-canonical=true
env:
SOURCE_DATE_EPOCH: ${{ env.SOURCE_DATE_EPOCH }}
- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: digest-${{ matrix.arch.platform }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
docker-meta:
needs: docker-build-push
name: Publish Docker metadata
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
registry:
- docker.io
- ghcr.io
steps:
- name: Download digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: ${{ runner.temp }}/digests
pattern: digest-*
merge-multiple: true
- name: Login to ${{ matrix.registry }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ${{ matrix.registry }}
username: ${{ matrix.registry == 'docker.io' && secrets.DOCKERHUB_USERNAME || github.actor }}
password: ${{ matrix.registry == 'docker.io' && secrets.DOCKERHUB_TOKEN || secrets.GITHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: ${{ matrix.registry }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}.{{minor}}.{{patch}}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Create and push manifest list
working-directory: ${{ runner.temp }}/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("--tag " + .) | join(" ")' <<< "${DOCKER_METADATA_OUTPUT_JSON}") \
$(printf '${{ matrix.registry }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: docker buildx imagetools inspect '${{ matrix.registry }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}'
================================================
FILE: .github/workflows/scan.yml
================================================
name: "Scheduled vulnerability scan"
on:
workflow_call:
inputs:
ref:
description: Branch, tag or SHA to scan.
type: string
required: false
default: ""
permissions:
contents: read
jobs:
osv-scanner:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref }}
# Go needed for scanning of v2.5.5 and earlier
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: stable
cache: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
# Releases v2.5.7 and earlier do not support Java 25
java-version: 21
- uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Scan
run: make scan
================================================
FILE: .github/workflows/schedule.yml
================================================
name: Scheduled build
on:
schedule:
- cron: "5 4 * * 0"
workflow_dispatch:
jobs:
main:
uses: ./.github/workflows/test.yml
================================================
FILE: .github/workflows/scheduled-scan.yml
================================================
name: "Scheduled vulnerability scan"
on:
schedule:
- cron: "20 3 * * *"
workflow_dispatch:
permissions:
contents: read
jobs:
release-version:
name: Get latest release tag
runs-on: ubuntu-latest
outputs:
tag_name: ${{ steps.tag-name.outputs.value }}
steps:
- id: tag-name
run: echo "value=$(curl --location --silent --fail "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" | jq --raw-output '.tag_name')" >> "${GITHUB_OUTPUT}"
scan-release:
name: Scan ${{ needs.release-version.outputs.tag_name }}
needs: release-version
uses: ./.github/workflows/scan.yml
with:
ref: ${{ needs.release-version.outputs.tag_name }}
scan-latest:
name: Scan latest
uses: ./.github/workflows/scan.yml
================================================
FILE: .github/workflows/test.yml
================================================
# Copyright the Hyperledger Fabric contributors. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
name: Test
on:
workflow_call:
inputs:
ref:
default: ""
required: false
type: string
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref }}
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
java-version: 25
- uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Build and Unit test
run: ./gradlew :fabric-chaincode-shim:build
intergationtest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref }}
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
java-version: 25
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "lts/*"
- uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Populate chaincode with latest java-version
run: |
./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/fabric-shim-api/repository publishShimPublicationToFabricRepository
./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/fabric-ledger-api/repository publishShimPublicationToFabricRepository
./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/bare-gradle/repository publishShimPublicationToFabricRepository
./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/bare-maven/repository publishShimPublicationToFabricRepository
./gradlew -I $GITHUB_WORKSPACE/fabric-chaincode-integration-test/chaincodebootstrap.gradle -PchaincodeRepoDir=$GITHUB_WORKSPACE/fabric-chaincode-integration-test/src/contracts/wrapper-maven/repository publishShimPublicationToFabricRepository
- name: Ensure that the Peer/weft tools are available
run: |
curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh | bash -s -- binary
npm install -g @hyperledger-labs/weft
# set the path and cfg env var for the rest of the step
echo "FABRIC_CFG_PATH=$GITHUB_WORKSPACE/config" >> $GITHUB_ENV
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
- name: versions
run: |
peer version
weft --version
- name: Integration Tests
run: ./gradlew :fabric-chaincode-integration-test:build
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref }}
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
java-version: 25
- uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Build Docker image
run: ./gradlew :fabric-chaincode-docker:buildImage
================================================
FILE: .gitignore
================================================
/.settings/
/.project
*.log
*.swp
.gradletasknamecache
.classpath
**/bin/
/build/
build/*
settings-gradle.lockfile
config/
_cfg
repository
.env
.gradle
/build/
out/
gradle.lockfile
!gradle/wrapper/gradle-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
local-config.yaml
gradle.properties
.vscode/
### Jekyll ###
.sass-cache
_site
================================================
FILE: CHANGELOG.md
================================================
# Changelog
Notable changes in each release are documented on the project's [GitHub releases](https://github.com/hyperledger/fabric-chaincode-java/releases) page. Change history from previous releases is retained below.
## v2.5.0
Thu Dec 8 09:02:17 GMT 2022
* [94cfadee](https://github.com/hyperledger/fabric-chaincode-java/commit/94cfadee) Move inactive maintainers to emeritus status
* [37bebee7](https://github.com/hyperledger/fabric-chaincode-java/commit/37bebee7) Adjust to using the Temurin JVM
* [0c9f44fb](https://github.com/hyperledger/fabric-chaincode-java/commit/0c9f44fb) Basic github actions workflow
* [d15f2cd1](https://github.com/hyperledger/fabric-chaincode-java/commit/d15f2cd1) Update pom.xml
* [1fba41b2](https://github.com/hyperledger/fabric-chaincode-java/commit/1fba41b2) Remove unrequired Maven wrapper directory Update Maven wrapper to latest version
* [3a2db82d](https://github.com/hyperledger/fabric-chaincode-java/commit/3a2db82d) Bump version to 2.5.0
* [35eabb0a](https://github.com/hyperledger/fabric-chaincode-java/commit/35eabb0a) PurgePrivateData
* [80a36ee4](https://github.com/hyperledger/fabric-chaincode-java/commit/80a36ee4) Swap to using the published fabric-protos libraries
* [dd551979](https://github.com/hyperledger/fabric-chaincode-java/commit/dd551979) Update MAINTAINERS.md
* [f25df1b6](https://github.com/hyperledger/fabric-chaincode-java/commit/f25df1b6) Add test for Logger.debug
* [d1d093b4](https://github.com/hyperledger/fabric-chaincode-java/commit/d1d093b4) Regular Maintainece Task
* [22c722fe](https://github.com/hyperledger/fabric-chaincode-java/commit/22c722fe) Update README.md
* [2c35c3ed](https://github.com/hyperledger/fabric-chaincode-java/commit/2c35c3ed) JSONPropertyIgnore only works on getter
* [02d1485a](https://github.com/hyperledger/fabric-chaincode-java/commit/02d1485a) Change from RocketChat to Discord
* [5608879e](https://github.com/hyperledger/fabric-chaincode-java/commit/5608879e) Temporarily remove nightly publish & Fix PR build
* [d13d3070](https://github.com/hyperledger/fabric-chaincode-java/commit/d13d3070) Fix transaction serializer usage
* [5388349d](https://github.com/hyperledger/fabric-chaincode-java/commit/5388349d) Remove the log4j dependency
## v2.4.1
Mon Dec 13 11:50:31 GMT 2021
* [bf054cb0](https://github.com/hyperledger/fabric-chaincode-java/commit/bf054cb0) Add a brief example for the -as-a-service
* [f9ada8f5](https://github.com/hyperledger/fabric-chaincode-java/commit/f9ada8f5) Chaincode-as-a-service main bootstrap method
## 2.4.0
Fri Nov 26 08:21:40 GMT 2021
Release 2.4.0
## v2.4.0-beta
Fri 13 Aug 2021 16:43:31 CEST
* [292c4ebe](https://github.com/hyperledger/fabric-chaincode-java/commit/292c4ebe) Update the build.gradle for publishing
## v2.3.1
Wed 21 Jul 2021 11:20:03 BST
* [6be7a724](https://github.com/hyperledger/fabric-chaincode-java/commit/6be7a724) Integration tests extended
* [66e25ea9](https://github.com/hyperledger/fabric-chaincode-java/commit/66e25ea9) NettyGrpcServer -- support mutual TLS
* [1128e7b2](https://github.com/hyperledger/fabric-chaincode-java/commit/1128e7b2) NettyGrpcServer: logger->LOGGER
* [b7b4ef12](https://github.com/hyperledger/fabric-chaincode-java/commit/b7b4ef12) NettyGrpcServer -- reformat code
* [3a98fc5e](https://github.com/hyperledger/fabric-chaincode-java/commit/3a98fc5e) NettyGrpcServer -- configure ALPN
* [63c12ffa](https://github.com/hyperledger/fabric-chaincode-java/commit/63c12ffa) NettyGrpcServerTest -- improve startAndStopTlsPassword, startAndStopTlsWithoutPassword test cases
* [5046eb79](https://github.com/hyperledger/fabric-chaincode-java/commit/5046eb79) Bump logback-classic in /examples/fabric-contract-example-maven
* [ab2a166d](https://github.com/hyperledger/fabric-chaincode-java/commit/ab2a166d) added tests
* [25706938](https://github.com/hyperledger/fabric-chaincode-java/commit/25706938) Add additional contracts for deployment test
* [e096d4f7](https://github.com/hyperledger/fabric-chaincode-java/commit/e096d4f7) Review ideas
* [7645bb9d](https://github.com/hyperledger/fabric-chaincode-java/commit/7645bb9d) Move to use Maven Wrapper
* [d212e2a7](https://github.com/hyperledger/fabric-chaincode-java/commit/d212e2a7) Upgrade gradle to v7
* [f1d6b7da](https://github.com/hyperledger/fabric-chaincode-java/commit/f1d6b7da) Gradle wrapper updated to the latest version
* [3f190ef5](https://github.com/hyperledger/fabric-chaincode-java/commit/3f190ef5) Transaction metadata tags updated
* [0d0c9280](https://github.com/hyperledger/fabric-chaincode-java/commit/0d0c9280) Update "master" branch references to "main"
* [ca69f15d](https://github.com/hyperledger/fabric-chaincode-java/commit/ca69f15d) Fix link in SECURITY.md
* [4c6cbf47](https://github.com/hyperledger/fabric-chaincode-java/commit/4c6cbf47) Correct condition
* [76c7fe45](https://github.com/hyperledger/fabric-chaincode-java/commit/76c7fe45) Cleanup files
* [70bdd194](https://github.com/hyperledger/fabric-chaincode-java/commit/70bdd194) Add in publishing of the nightly master branch drivers
* [b51eac20](https://github.com/hyperledger/fabric-chaincode-java/commit/b51eac20) Change FABRIC_VERSION to latest tag
* [28dfb24b](https://github.com/hyperledger/fabric-chaincode-java/commit/28dfb24b) fix fabric-contract-example-maven/pom.xml
* [ff48941c](https://github.com/hyperledger/fabric-chaincode-java/commit/ff48941c) Logging Tests Reset Correctly
* [cc31ae01](https://github.com/hyperledger/fabric-chaincode-java/commit/cc31ae01) [FABCJ-214](https://jira.hyperledger.org/browse/FABCJ-214) - Java chaincode gRPC server
* [06f72193](https://github.com/hyperledger/fabric-chaincode-java/commit/06f72193) Fix "build shadowJar" error
* [278e9f8e](https://github.com/hyperledger/fabric-chaincode-java/commit/278e9f8e) [FABCJ-187](https://jira.hyperledger.org/browse/FABCJ-187) Add max inbound msg size configuration
* [bf4f30aa](https://github.com/hyperledger/fabric-chaincode-java/commit/bf4f30aa) Fix javadoc build
* [9e403b6d](https://github.com/hyperledger/fabric-chaincode-java/commit/9e403b6d) Fix JavaDoc link to Compatibility documentation
* [57678eea](https://github.com/hyperledger/fabric-chaincode-java/commit/57678eea) Bump version to 2.3.1
* [91e6001d](https://github.com/hyperledger/fabric-chaincode-java/commit/91e6001d) [FABCJ-290](https://jira.hyperledger.org/browse/FABCJ-290) Add release guide
* [0deb7e0d](https://github.com/hyperledger/fabric-chaincode-java/commit/0deb7e0d) [FABCJ-293](https://jira.hyperledger.org/browse/FABCJ-293) Remove gradle from image
* [2dfe17c1](https://github.com/hyperledger/fabric-chaincode-java/commit/2dfe17c1) [FABCJ-291](https://jira.hyperledger.org/browse/FABCJ-291) Startkey needs additional checks For the open ended query, the start and empty keys are empty from the chaincode. However, in the shim, if the start key is an empty key, it is replaced with 0x01 which is nothing but a namespace for the non-composite key.
* [21d81193](https://github.com/hyperledger/fabric-chaincode-java/commit/21d81193) Update doc links
* [78ed0157](https://github.com/hyperledger/fabric-chaincode-java/commit/78ed0157) [FABCJ-288](https://jira.hyperledger.org/browse/FABCJ-288) fix: simple key end of range
* [90f6c3c2](https://github.com/hyperledger/fabric-chaincode-java/commit/90f6c3c2) Update dependencies
* [526d1cc8](https://github.com/hyperledger/fabric-chaincode-java/commit/526d1cc8) [FABCJ-284](https://jira.hyperledger.org/browse/FABCJ-284) Broken link
* [7f722053](https://github.com/hyperledger/fabric-chaincode-java/commit/7f722053) force rebuild
* [9a42effb](https://github.com/hyperledger/fabric-chaincode-java/commit/9a42effb) [FABCJ-285](https://jira.hyperledger.org/browse/FABCJ-285) Remove incorrect log point
* [c2367768](https://github.com/hyperledger/fabric-chaincode-java/commit/c2367768) Clean up Fabric Version Methodology
* [88da28f6](https://github.com/hyperledger/fabric-chaincode-java/commit/88da28f6) [FAB-17777](https://jira.hyperledger.org/browse/FAB-17777) Create basic settings.yaml
* [a6b00f2d](https://github.com/hyperledger/fabric-chaincode-java/commit/a6b00f2d) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update javadoc 2.x link
* [96fa4d6e](https://github.com/hyperledger/fabric-chaincode-java/commit/96fa4d6e) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update docs to handle new branch
* [ff031f2d](https://github.com/hyperledger/fabric-chaincode-java/commit/ff031f2d) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Bump version number to 3.0.0 - in order to not contradict release-2.x branch
* [35a5159d](https://github.com/hyperledger/fabric-chaincode-java/commit/35a5159d) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update docker image version to 2.1
* [67af7977](https://github.com/hyperledger/fabric-chaincode-java/commit/67af7977) [FABCJ-280](https://jira.hyperledger.org/browse/FABCJ-280) Copy chaincode into temporary directory before building
* [e69168cb](https://github.com/hyperledger/fabric-chaincode-java/commit/e69168cb) [FABCJ-276](https://jira.hyperledger.org/browse/FABCJ-276) Access localmspid
* [cc673036](https://github.com/hyperledger/fabric-chaincode-java/commit/cc673036) [FABCN-359](https://jira.hyperledger.org/browse/FABCN-359) Ledger Class
* [f0689360](https://github.com/hyperledger/fabric-chaincode-java/commit/f0689360) [FABCJ-273](https://jira.hyperledger.org/browse/FABCJ-273) Show release-2.0 Javadoc
* [364cae9d](https://github.com/hyperledger/fabric-chaincode-java/commit/364cae9d) [FABCJ-269](https://jira.hyperledger.org/browse/FABCJ-269) Compatibility Matrix
* [89ffb592](https://github.com/hyperledger/fabric-chaincode-java/commit/89ffb592) [FABCJ-273](https://jira.hyperledger.org/browse/FABCJ-273) Prepare next release v2.1.0
* [6c1cdba0](https://github.com/hyperledger/fabric-chaincode-java/commit/6c1cdba0) Java chaincode gRPC server for run external chaincode add NettyGrpcServer with method /Connect for start chat with peer without TLS add example external chaincode
## v2.3.0
Tue 3 Nov 2020 14:20:11 GMT
* [081d5c8](https://github.com/hyperledger/fabric-chaincode-java/commit/081d5c8) Bump version to 2.2.2
* [b494824](https://github.com/hyperledger/fabric-chaincode-java/commit/b494824) [FABCJ-290](https://jira.hyperledger.org/browse/FABCJ-290) Add release guide
## v2.2.1
Wed 7 Oct 2020 16:21:53 BST
* [cef231c](https://github.com/hyperledger/fabric-chaincode-java/commit/cef231c) [FABCJ-293](https://jira.hyperledger.org/browse/FABCJ-293) Remove gradle from image
* [d2643ef](https://github.com/hyperledger/fabric-chaincode-java/commit/d2643ef) Minor Performance Improvements
* [703558c](https://github.com/hyperledger/fabric-chaincode-java/commit/703558c) [FABCJ-291](https://jira.hyperledger.org/browse/FABCJ-291) Startkey needs additional checks For the open ended query, the start and empty keys are empty from the chaincode. However, in the shim, if the start key is an empty key, it is replaced with 0x01 which is nothing but a namespace for the non-composite key.
* [f35ae08](https://github.com/hyperledger/fabric-chaincode-java/commit/f35ae08) Fix tagging of fabric-javaenv image
* [cb31d36](https://github.com/hyperledger/fabric-chaincode-java/commit/cb31d36) Bump version to 2.2.1
## v2.2.0
Thu 2 Jul 11:28:13 BST 2020
* [32c8201](https://github.com/hyperledger/fabric-chaincode-java/commit/32c8201) [FABCJ-289](https://jira.hyperledger.org/browse/FABCJ-289) release: 2.2.0 LTS
* [0948234](https://github.com/hyperledger/fabric-chaincode-java/commit/0948234) [FABCJ-288](https://jira.hyperledger.org/browse/FABCJ-288) fix: simple key end of range
* [8b06be2](https://github.com/hyperledger/fabric-chaincode-java/commit/8b06be2) [FABCJ-286](https://jira.hyperledger.org/browse/FABCJ-286) Prepare 2.1.2
## v2.1.1
Mon 18 May 09:09:24 BST 2020
* [f0f958e](https://github.com/hyperledger/fabric-chaincode-java/commit/f0f958e) [FABCJ-284](https://jira.hyperledger.org/browse/FABCJ-284) Broken docs link
* [b89c464](https://github.com/hyperledger/fabric-chaincode-java/commit/b89c464) [FABCJ-285](https://jira.hyperledger.org/browse/FABCJ-285) Remove incorrect log point
* [93ff6bb](https://github.com/hyperledger/fabric-chaincode-java/commit/93ff6bb) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Bump version number to 2.1.1
## v2.1.0
Thu 9 Apr 2020 14:13:36 BST
* [72e6f78](https://github.com/hyperledger/fabric-chaincode-java/commit/72e6f78) [FABCJ-283](https://jira.hyperledger.org/browse/FABCJ-283) Update docker image version
* [54606f8](https://github.com/hyperledger/fabric-chaincode-java/commit/54606f8) [FABCJ-269](https://jira.hyperledger.org/browse/FABCJ-269) Compatibility Matrix
## v2.0.1
Wed 4 Mar 16:38:58 GMT 2020
* [8cb6a25](https://github.com/hyperledger/fabric-chaincode-java/commit/8cb6a25) [FAB-16136](https://jira.hyperledger.org/browse/FAB-16136) Do not run tests in chaincode container
* [3710641](https://github.com/hyperledger/fabric-chaincode-java/commit/3710641) [FABCJ-280](https://jira.hyperledger.org/browse/FABCJ-280) Copy chaincode into temporary directory before building
* [a25a7d6](https://github.com/hyperledger/fabric-chaincode-java/commit/a25a7d6) [FABCJ-276](https://jira.hyperledger.org/browse/FABCJ-276) Access localmspid
## v2.0.0
Fri 24 Jan 10:26:03 GMT 2020
* [659a1c4](https://github.com/hyperledger/fabric-chaincode-java/commit/659a1c4) Port fixes from master branch for Coverage & typos
* [9cf1e6a](https://github.com/hyperledger/fabric-chaincode-java/commit/9cf1e6a) [FABCI-482](https://jira.hyperledger.org/browse/FABCI-482) Update Nexus URL's to Artifactory
* [7ab7145](https://github.com/hyperledger/fabric-chaincode-java/commit/7ab7145) Fix typos in README.md
* [67fdc40](https://github.com/hyperledger/fabric-chaincode-java/commit/67fdc40) [FABCJ-259](https://jira.hyperledger.org/browse/FABCJ-259) Pagination Fix
* [1609425](https://github.com/hyperledger/fabric-chaincode-java/commit/1609425) Update maintainers list
* [1a45e3d](https://github.com/hyperledger/fabric-chaincode-java/commit/1a45e3d) [FABCJ-95](https://jira.hyperledger.org/browse/FABCJ-95) Checkstyle
## v2.0.0-beta
Thu 12 Dec 12:45:44 GMT 2019
* [4a13009](https://github.com/hyperledger/fabric-chaincode-java/commit/4a13009) Add OWASP dependency checks to build
* [44c96d7](https://github.com/hyperledger/fabric-chaincode-java/commit/44c96d7) FABCJ-258 Add latest image tag in AZP pipeline
* [e1d53bf](https://github.com/hyperledger/fabric-chaincode-java/commit/e1d53bf) Remove -SNAPSHOT from package version variable
* [fedc2ef](https://github.com/hyperledger/fabric-chaincode-java/commit/fedc2ef) Improve integration test reliability
* [6fd5507](https://github.com/hyperledger/fabric-chaincode-java/commit/6fd5507) [FABCJ-257] Rationalize examples
* [5d3cd53](https://github.com/hyperledger/fabric-chaincode-java/commit/5d3cd53) [FABCJ-160] Char support
* [e32e404](https://github.com/hyperledger/fabric-chaincode-java/commit/e32e404) [FABCJ-183] Extra properties appear in JSON from Java Objects
* [7f3c4e3](https://github.com/hyperledger/fabric-chaincode-java/commit/7f3c4e3) [FAB-17138](https://jira.hyperledger.org/browse/FAB-17138) Publish docker images to nexus
* [b52d26a](https://github.com/hyperledger/fabric-chaincode-java/commit/b52d26a) [FAB-15634](https://jira.hyperledger.org/browse/FAB-15634) Annotations for Serializer
* [207bd94](https://github.com/hyperledger/fabric-chaincode-java/commit/207bd94) [FAB-17100](https://jira.hyperledger.org/browse/FAB-17100) Default Thread Pool not set correctly
* [f50a4ed](https://github.com/hyperledger/fabric-chaincode-java/commit/f50a4ed) [FAB-16712](https://jira.hyperledger.org/browse/FAB-16712) Disable stalebot
* [ee8a1f4](https://github.com/hyperledger/fabric-chaincode-java/commit/ee8a1f4) Update javadoc location in readme
* [3951dca](https://github.com/hyperledger/fabric-chaincode-java/commit/3951dca) Fix git user email/name config in azure pipeline
* [55ad1b9](https://github.com/hyperledger/fabric-chaincode-java/commit/55ad1b9) Update javadoc build to use Hyperledger Bot
* [4680efc](https://github.com/hyperledger/fabric-chaincode-java/commit/4680efc) Publish javadoc
* [d4981a3](https://github.com/hyperledger/fabric-chaincode-java/commit/d4981a3) Fix the name of the docker image
* [6553ffc](https://github.com/hyperledger/fabric-chaincode-java/commit/6553ffc) Update readme
* [3b029a8](https://github.com/hyperledger/fabric-chaincode-java/commit/3b029a8) Fix the name of the docker image
* [d01eeff](https://github.com/hyperledger/fabric-chaincode-java/commit/d01eeff) Add artifacts to build result
* [3c2c27c](https://github.com/hyperledger/fabric-chaincode-java/commit/3c2c27c) [FAB-16712](https://jira.hyperledger.org/browse/FAB-16712) Update contributing guide
* [d13e0c0](https://github.com/hyperledger/fabric-chaincode-java/commit/d13e0c0) Next steps in publishing
* [75a0bed](https://github.com/hyperledger/fabric-chaincode-java/commit/75a0bed) Next steps in publishing
* [fd2e21a](https://github.com/hyperledger/fabric-chaincode-java/commit/fd2e21a) Next steps in publishing
* [5618de6](https://github.com/hyperledger/fabric-chaincode-java/commit/5618de6) Push the snapshot docker images to nexus
* [5a11c6e](https://github.com/hyperledger/fabric-chaincode-java/commit/5a11c6e) Push the snapshot docker images to nexus
* [4eff463](https://github.com/hyperledger/fabric-chaincode-java/commit/4eff463) [FAB-16315](https://jira.hyperledger.org/browse/FAB-16315) Improved Load Ability
* [11a26ce](https://github.com/hyperledger/fabric-chaincode-java/commit/11a26ce) Fix Azure Pipelines
* [7b3e509](https://github.com/hyperledger/fabric-chaincode-java/commit/7b3e509) [FAB-16711](https://jira.hyperledger.org/browse/FAB-16711) Azure pipelines
* [a3304ec](https://github.com/hyperledger/fabric-chaincode-java/commit/a3304ec) [FAB-16707](https://jira.hyperledger.org/browse/FAB-16707) Remove Gradle warnings
* [af3dec0](https://github.com/hyperledger/fabric-chaincode-java/commit/af3dec0) [IN-68] Add default GitHub SECURITY policy
* [88b9397](https://github.com/hyperledger/fabric-chaincode-java/commit/88b9397) [FAB-16680](https://jira.hyperledger.org/browse/FAB-16680) Fix cloudflare error on jitpack.io
* [f6076eb](https://github.com/hyperledger/fabric-chaincode-java/commit/f6076eb) [FAB-16669](https://jira.hyperledger.org/browse/FAB-16669) WIP: Use native Java 11 ALPN support
* [5520053](https://github.com/hyperledger/fabric-chaincode-java/commit/5520053) [FAB-16669](https://jira.hyperledger.org/browse/FAB-16669) Update gRPC and Protocol Buffers code
* [abff28f](https://github.com/hyperledger/fabric-chaincode-java/commit/abff28f) [FAB-16655](https://jira.hyperledger.org/browse/FAB-16655) Warnings as errors for Java chaincode docs
* [50e75bf](https://github.com/hyperledger/fabric-chaincode-java/commit/50e75bf) [FAB-16655](https://jira.hyperledger.org/browse/FAB-16655) Warnings as errors for Java chaincode
* [d79f5a6](https://github.com/hyperledger/fabric-chaincode-java/commit/d79f5a6) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Remove tests from Docker image build
* [35d5884](https://github.com/hyperledger/fabric-chaincode-java/commit/35d5884) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Various chaincode deployment updates
* [12b5243](https://github.com/hyperledger/fabric-chaincode-java/commit/12b5243) [FAB-16493](https://jira.hyperledger.org/browse/FAB-16493) Fixed gradle build on windows
* [2f6be19](https://github.com/hyperledger/fabric-chaincode-java/commit/2f6be19) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Remove cglib dependency
* [56c533e](https://github.com/hyperledger/fabric-chaincode-java/commit/56c533e) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Upgrade Docker image to Java 11
* [5dbbea7](https://github.com/hyperledger/fabric-chaincode-java/commit/5dbbea7) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Replace org.reflections with classgraph
* [059d043](https://github.com/hyperledger/fabric-chaincode-java/commit/059d043) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Add javax.xml.bind dependency for Java 11
* [cbe663b](https://github.com/hyperledger/fabric-chaincode-java/commit/cbe663b) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Upgrade to Gradle 5.6.2 and Maven 3.6.2
* [887153c](https://github.com/hyperledger/fabric-chaincode-java/commit/887153c) [FAB-6415](https://jira.hyperledger.org/browse/FAB-6415) Add javax.annotation dependency for Java 11
* [66e9079](https://github.com/hyperledger/fabric-chaincode-java/commit/66e9079) [FAB-16489](https://jira.hyperledger.org/browse/FAB-16489) Add CODEOWNERS
* [182c050](https://github.com/hyperledger/fabric-chaincode-java/commit/182c050) [FAB-15507](https://jira.hyperledger.org/browse/FAB-15507) Add doc
* [1a38b84](https://github.com/hyperledger/fabric-chaincode-java/commit/1a38b84) [FABN-1320] Remove sed from git_tag.sh script
* [25ed6c1](https://github.com/hyperledger/fabric-chaincode-java/commit/25ed6c1) [FABN-1320] Fix git_tag.sh
* [f47f601](https://github.com/hyperledger/fabric-chaincode-java/commit/f47f601) [FAB-15929](https://jira.hyperledger.org/browse/FAB-15929) Add getPrivateDataHash support
* [4371d07](https://github.com/hyperledger/fabric-chaincode-java/commit/4371d07) [FAB-16217](https://jira.hyperledger.org/browse/FAB-16217) Do not load JSON Schema schema from network
* [44d76f4](https://github.com/hyperledger/fabric-chaincode-java/commit/44d76f4) [FAB-15895](https://jira.hyperledger.org/browse/FAB-15895) Added client identity to context
* [9169e14](https://github.com/hyperledger/fabric-chaincode-java/commit/9169e14) New maintainer application
* [12309b5](https://github.com/hyperledger/fabric-chaincode-java/commit/12309b5) [FAB-16091](https://jira.hyperledger.org/browse/FAB-16091) Handle invalid contract name
* [e8ca970](https://github.com/hyperledger/fabric-chaincode-java/commit/e8ca970) [FAB-15647](https://jira.hyperledger.org/browse/FAB-15647) Fix markup of README
* [360d75a](https://github.com/hyperledger/fabric-chaincode-java/commit/360d75a) [FAB-15883](https://jira.hyperledger.org/browse/FAB-15883) Removed swagger annotations
* [25c5be6](https://github.com/hyperledger/fabric-chaincode-java/commit/25c5be6) [FAB-15615](https://jira.hyperledger.org/browse/FAB-15615) Add ChaincodeException support
* [9077581](https://github.com/hyperledger/fabric-chaincode-java/commit/9077581) [FAB-15823](https://jira.hyperledger.org/browse/FAB-15823) Fix getStringPayload npe
* [e163d3f](https://github.com/hyperledger/fabric-chaincode-java/commit/e163d3f) [FAB-15743](https://jira.hyperledger.org/browse/FAB-15743) Align Context
* [5ad6ed8](https://github.com/hyperledger/fabric-chaincode-java/commit/5ad6ed8) [FAB-15507](https://jira.hyperledger.org/browse/FAB-15507) Exclude unnecessary contract javadoc
* [9cc6553](https://github.com/hyperledger/fabric-chaincode-java/commit/9cc6553) [FAB-15720](https://jira.hyperledger.org/browse/FAB-15720) prevent duplicate transactions
* [f87de8e](https://github.com/hyperledger/fabric-chaincode-java/commit/f87de8e) [FAB-15632](https://jira.hyperledger.org/browse/FAB-15632) Add name element to transaction annotation
* [d726175](https://github.com/hyperledger/fabric-chaincode-java/commit/d726175) [FAB-13803](https://jira.hyperledger.org/browse/FAB-13803) Parameter Marshalling
* [72dc716](https://github.com/hyperledger/fabric-chaincode-java/commit/72dc716) [FAB-15214](https://jira.hyperledger.org/browse/FAB-15214) Remove init annotation
* [509bfbf](https://github.com/hyperledger/fabric-chaincode-java/commit/509bfbf) [FAB-13802](https://jira.hyperledger.org/browse/FAB-13802) Metadata Support
* [0467032](https://github.com/hyperledger/fabric-chaincode-java/commit/0467032) Application to be consider for maintainer of this repo
* [526f36d](https://github.com/hyperledger/fabric-chaincode-java/commit/526f36d) [FAB-13802](https://jira.hyperledger.org/browse/FAB-13802) Return types update
* [1662390](https://github.com/hyperledger/fabric-chaincode-java/commit/1662390) [FAB-13912](https://jira.hyperledger.org/browse/FAB-13912) Implement new interfaces
* [bd1c269](https://github.com/hyperledger/fabric-chaincode-java/commit/bd1c269) [FAB-14961](https://jira.hyperledger.org/browse/FAB-14961) Update to the FAQ
* [dc02c3b](https://github.com/hyperledger/fabric-chaincode-java/commit/dc02c3b) [FAB-14995](https://jira.hyperledger.org/browse/FAB-14995) Prepare for next release
## v2.0.0-alpha
Sun Apr 9 15:37:09 IDT 2019
* [b62740c](https://github.com/hyperledger/fabric-chaincode-java/commit/b62740c) [FAB-13798](https://jira.hyperledger.org/browse/FAB-13798) New interfaces
* [8235149](https://github.com/hyperledger/fabric-chaincode-java/commit/8235149) [FAB-13795](https://jira.hyperledger.org/browse/FAB-13795) Contract definition
* [762a955](https://github.com/hyperledger/fabric-chaincode-java/commit/762a955) [FAB-13800](https://jira.hyperledger.org/browse/FAB-13800) Transaction Context
* [351acb5](https://github.com/hyperledger/fabric-chaincode-java/commit/351acb5) [FAB-13794](https://jira.hyperledger.org/browse/FAB-13794) New Annotations
* [3e13a57](https://github.com/hyperledger/fabric-chaincode-java/commit/3e13a57) [FAB-12960](https://jira.hyperledger.org/browse/FAB-12960) Adding cc without main method
* [40bf2c1](https://github.com/hyperledger/fabric-chaincode-java/commit/40bf2c1) [FAB-14533](https://jira.hyperledger.org/browse/FAB-14533) Updating integration tests
* [b17d8a2](https://github.com/hyperledger/fabric-chaincode-java/commit/b17d8a2) [FAB-12504](https://jira.hyperledger.org/browse/FAB-12504) Added maven integration test.
* [0e76b72](https://github.com/hyperledger/fabric-chaincode-java/commit/0e76b72) [FAB-14522](https://jira.hyperledger.org/browse/FAB-14522) README update: sdk compatibility
* [e5d3e40](https://github.com/hyperledger/fabric-chaincode-java/commit/e5d3e40) [FAB-14460](https://jira.hyperledger.org/browse/FAB-14460) Better chaincode source check
* [0adaf35](https://github.com/hyperledger/fabric-chaincode-java/commit/0adaf35) [FAB-13490](https://jira.hyperledger.org/browse/FAB-13490) javaenv image based on openjdk:slim-8
* [e33b4bd](https://github.com/hyperledger/fabric-chaincode-java/commit/e33b4bd) [FAB-13672](https://jira.hyperledger.org/browse/FAB-13672) stop using deprecated left closure
* [c3e342a](https://github.com/hyperledger/fabric-chaincode-java/commit/c3e342a) [FAB-13097](https://jira.hyperledger.org/browse/FAB-13097) Getting correct jar
* [cc76d2f](https://github.com/hyperledger/fabric-chaincode-java/commit/cc76d2f) [FAB-13097](https://jira.hyperledger.org/browse/FAB-13097) Adding shim 1.3.0 to docker image
* [b22858b](https://github.com/hyperledger/fabric-chaincode-java/commit/b22858b) Configure Stale ProBot
* [1279d2c](https://github.com/hyperledger/fabric-chaincode-java/commit/1279d2c) [FAB-13436](https://jira.hyperledger.org/browse/FAB-13436) multistage docker build
* [035a7d2](https://github.com/hyperledger/fabric-chaincode-java/commit/035a7d2) [FAB-13243](https://jira.hyperledger.org/browse/FAB-13243) fix javaenv docker build tag
* [ad89bbb](https://github.com/hyperledger/fabric-chaincode-java/commit/ad89bbb) [FAB-13248](https://jira.hyperledger.org/browse/FAB-13248) Update dependencies for sonatype
* [cea4db0](https://github.com/hyperledger/fabric-chaincode-java/commit/cea4db0) [FAB-13229](https://jira.hyperledger.org/browse/FAB-13229) Prepare for next release (2.0.0 on master)
* [4c6cd6c](https://github.com/hyperledger/fabric-chaincode-java/commit/4c6cd6c) [FAB-13236](https://jira.hyperledger.org/browse/FAB-13236) Publish jars to sonatype
## v1.4.0-rc1
Sun Apr 7 15:37:00 IDT 2019
* [2d26e5d](https://github.com/hyperledger/fabric-chaincode-java/commit/2d26e5d) [FAB-13117](https://jira.hyperledger.org/browse/FAB-13117) Release java chaincode 1.4.0-rc1
* [3628832](https://github.com/hyperledger/fabric-chaincode-java/commit/3628832) [FAB-13194](https://jira.hyperledger.org/browse/FAB-13194) Script to publish javaenv multiarch image
* [455100c](https://github.com/hyperledger/fabric-chaincode-java/commit/455100c) [FAB-12426](https://jira.hyperledger.org/browse/FAB-12426) Fix java chaincode return status.
* [ea26118](https://github.com/hyperledger/fabric-chaincode-java/commit/ea26118) [FAB-12197](https://jira.hyperledger.org/browse/FAB-12197) Integration tests
* [3b61085](https://github.com/hyperledger/fabric-chaincode-java/commit/3b61085) [FAB-12110](https://jira.hyperledger.org/browse/FAB-12110) SimpleAsset java chaincode example
* [b46fc70](https://github.com/hyperledger/fabric-chaincode-java/commit/b46fc70) [FAB-12328](https://jira.hyperledger.org/browse/FAB-12328) java cc pagination
* [68685dc](https://github.com/hyperledger/fabric-chaincode-java/commit/68685dc) [FAB-12469](https://jira.hyperledger.org/browse/FAB-12469) Java sbe tests
* [748ea9f](https://github.com/hyperledger/fabric-chaincode-java/commit/748ea9f) [FAB-12468](https://jira.hyperledger.org/browse/FAB-12468) Utility classes for java sbe
* [b4b3a87](https://github.com/hyperledger/fabric-chaincode-java/commit/b4b3a87) [FAB-12467](https://jira.hyperledger.org/browse/FAB-12467) State-based endorsement
* [c32c4c4](https://github.com/hyperledger/fabric-chaincode-java/commit/c32c4c4) [FAB-12568](https://jira.hyperledger.org/browse/FAB-12568) Adding identities to JavaCC
* [fb81132](https://github.com/hyperledger/fabric-chaincode-java/commit/fb81132) Fix LFID for gennadyl
* [7522309](https://github.com/hyperledger/fabric-chaincode-java/commit/7522309) Retire dormant maintainers, suggest new nomination
* [321db66](https://github.com/hyperledger/fabric-chaincode-java/commit/321db66) [FAB-12444](https://jira.hyperledger.org/browse/FAB-12444) Update java cc to baseimage 0.4.14
* [aa177d2](https://github.com/hyperledger/fabric-chaincode-java/commit/aa177d2) [FAB-12347](https://jira.hyperledger.org/browse/FAB-12347) Update java cc to baseimage 0.4.13
* [e9c5602](https://github.com/hyperledger/fabric-chaincode-java/commit/e9c5602) [FAB-12223](https://jira.hyperledger.org/browse/FAB-12223) Adding FAQ file
* [af01201](https://github.com/hyperledger/fabric-chaincode-java/commit/af01201) [FAB-12278](https://jira.hyperledger.org/browse/FAB-12278) Fixing java cc build script
* [52cc6bd](https://github.com/hyperledger/fabric-chaincode-java/commit/52cc6bd) [FAB-12157](https://jira.hyperledger.org/browse/FAB-12157) Hadling chaincode in default package
* [8dcd819](https://github.com/hyperledger/fabric-chaincode-java/commit/8dcd819) [FAB-12152](https://jira.hyperledger.org/browse/FAB-12152) Prepare for next release (1.4.0 on master)
* [cc91af5](https://github.com/hyperledger/fabric-chaincode-java/commit/cc91af5) [FAB-12152](https://jira.hyperledger.org/browse/FAB-12152) Prepare for next release (1.3.0 on master)
* [9cbb36c](https://github.com/hyperledger/fabric-chaincode-java/commit/9cbb36c) [FAB-10525](https://jira.hyperledger.org/browse/FAB-10525) Fix the bug getStateByPartialCompositeKey
## v1.3.0-rc1
Tue Sep 25 15:25:05 EDT 2018
* [224bc4d](https://github.com/hyperledger/fabric-chaincode-java/commit/224bc4d) [FAB-12160](https://jira.hyperledger.org/browse/FAB-12160) Release fabric-chaincode-java v1.3.0-rc1
* [333d91b](https://github.com/hyperledger/fabric-chaincode-java/commit/333d91b) [FAB-12129](https://jira.hyperledger.org/browse/FAB-12129) Update baseimage version
* [01dd207](https://github.com/hyperledger/fabric-chaincode-java/commit/01dd207) [FAB-12115](https://jira.hyperledger.org/browse/FAB-12115) Fix groupId in shim jars
* [5d7ed1c](https://github.com/hyperledger/fabric-chaincode-java/commit/5d7ed1c) [FAB-9519](https://jira.hyperledger.org/browse/FAB-9519) Java shim readmy and tutorial
* [44a1367](https://github.com/hyperledger/fabric-chaincode-java/commit/44a1367) [FAB-12017](https://jira.hyperledger.org/browse/FAB-12017) Adding java docs
* [56e2a11](https://github.com/hyperledger/fabric-chaincode-java/commit/56e2a11) [FAB-11839](https://jira.hyperledger.org/browse/FAB-11839) Adding FVT tests
* [ac70a6f](https://github.com/hyperledger/fabric-chaincode-java/commit/ac70a6f) [FAB-10032](https://jira.hyperledger.org/browse/FAB-10032) Adding unit test
* [ac6c906](https://github.com/hyperledger/fabric-chaincode-java/commit/ac6c906) [FAB-11750](https://jira.hyperledger.org/browse/FAB-11750) Updating version to 1.3.0
* [e80ba7c](https://github.com/hyperledger/fabric-chaincode-java/commit/e80ba7c) [FAB-11288](https://jira.hyperledger.org/browse/FAB-11288) Adding private data functions
* [79497bc](https://github.com/hyperledger/fabric-chaincode-java/commit/79497bc) [FAB-11741](https://jira.hyperledger.org/browse/FAB-11741) Reformat code
* [71ca2a2](https://github.com/hyperledger/fabric-chaincode-java/commit/71ca2a2) [FAB-11664](https://jira.hyperledger.org/browse/FAB-11664) Enable separate docker build
* [52f2c8b](https://github.com/hyperledger/fabric-chaincode-java/commit/52f2c8b) [FAB-11485](https://jira.hyperledger.org/browse/FAB-11485) Fixing empty proposal handling
* [2b35a46](https://github.com/hyperledger/fabric-chaincode-java/commit/2b35a46) [FAB-11304](https://jira.hyperledger.org/browse/FAB-11304) Handling READY message from peer
* [4b27549](https://github.com/hyperledger/fabric-chaincode-java/commit/4b27549) [FAB-9380](https://jira.hyperledger.org/browse/FAB-9380) remove FSM from java chaincode shim
* [f5e6fb4](https://github.com/hyperledger/fabric-chaincode-java/commit/f5e6fb4) [FAB-9920](https://jira.hyperledger.org/browse/FAB-9920) Java shim mutual TLS
* [d295c96](https://github.com/hyperledger/fabric-chaincode-java/commit/d295c96) [FAB-9424](https://jira.hyperledger.org/browse/FAB-9424) Adding docker build support
* [1cb0493](https://github.com/hyperledger/fabric-chaincode-java/commit/1cb0493) [FAB-10845](https://jira.hyperledger.org/browse/FAB-10845) Remove protos files
* [6c8abf4](https://github.com/hyperledger/fabric-chaincode-java/commit/6c8abf4) [FAB-9416](https://jira.hyperledger.org/browse/FAB-9416): Add gradle task to update protos
* [e3be99e](https://github.com/hyperledger/fabric-chaincode-java/commit/e3be99e) [FAB-9407](https://jira.hyperledger.org/browse/FAB-9407): Extract JavaCC shim protos
* [e4c9867](https://github.com/hyperledger/fabric-chaincode-java/commit/e4c9867) [FAB-9359](https://jira.hyperledger.org/browse/FAB-9359) add CODE_OF_CONDUCT.md and other docs
* [8772201](https://github.com/hyperledger/fabric-chaincode-java/commit/8772201) [FAB-9063](https://jira.hyperledger.org/browse/FAB-9063) Provide link to Fabric committers
* [4a9406b](https://github.com/hyperledger/fabric-chaincode-java/commit/4a9406b) Add Maintainers to fabric-chaincode-java
* [091a081](https://github.com/hyperledger/fabric-chaincode-java/commit/091a081) [FAB-8986](https://jira.hyperledger.org/browse/FAB-8986): Harden gradle build configuration
* [bb958eb](https://github.com/hyperledger/fabric-chaincode-java/commit/bb958eb) [FAB-8346](https://jira.hyperledger.org/browse/FAB-8346) sync chaincode proto files w/ fabric
* [c399853](https://github.com/hyperledger/fabric-chaincode-java/commit/c399853) [FAB-7989](https://jira.hyperledger.org/browse/FAB-7989) --peerAddress should be --peer.address
* [308eb63](https://github.com/hyperledger/fabric-chaincode-java/commit/308eb63) [FAB-7626](https://jira.hyperledger.org/browse/FAB-7626) Move to Gradle 4.4.1
* [d73edd6](https://github.com/hyperledger/fabric-chaincode-java/commit/d73edd6) [FAB-7294](https://jira.hyperledger.org/browse/FAB-7294) enable shim jar publication
* [d9c463e](https://github.com/hyperledger/fabric-chaincode-java/commit/d9c463e) [FAB-7091](https://jira.hyperledger.org/browse/FAB-7091) Extract StreamObserver out of ChaincodeBase
* [e3644f4](https://github.com/hyperledger/fabric-chaincode-java/commit/e3644f4) [FAB-6889](https://jira.hyperledger.org/browse/FAB-6889) add channel ID to chaincode message
* [2eda08b](https://github.com/hyperledger/fabric-chaincode-java/commit/2eda08b) [FAB-6726](https://jira.hyperledger.org/browse/FAB-6726) move to gradle 4.2.1
* [5cf4f73](https://github.com/hyperledger/fabric-chaincode-java/commit/5cf4f73) [FAB-3650](https://jira.hyperledger.org/browse/FAB-3650) add getBinding() API
* [a3b7d71](https://github.com/hyperledger/fabric-chaincode-java/commit/a3b7d71) [FAB-3649](https://jira.hyperledger.org/browse/FAB-3649) add getTransient() API
* [3cb86b0](https://github.com/hyperledger/fabric-chaincode-java/commit/3cb86b0) [FAB-3648](https://jira.hyperledger.org/browse/FAB-3648) add getCreator() API
* [5982e40](https://github.com/hyperledger/fabric-chaincode-java/commit/5982e40) [FAB-3653](https://jira.hyperledger.org/browse/FAB-3653) add getTxTimestamp() API
* [5566a62](https://github.com/hyperledger/fabric-chaincode-java/commit/5566a62) [FAB-6681](https://jira.hyperledger.org/browse/FAB-6681) Add code coverage report and verification
* [64de43a](https://github.com/hyperledger/fabric-chaincode-java/commit/64de43a) [FAB-6637](https://jira.hyperledger.org/browse/FAB-6637) add license check to fabric-chaincode-java
* [9f2f4f9](https://github.com/hyperledger/fabric-chaincode-java/commit/9f2f4f9) [FAB-3470](https://jira.hyperledger.org/browse/FAB-3470) update composite key format
* [61b8fc2](https://github.com/hyperledger/fabric-chaincode-java/commit/61b8fc2) [FAB-3651](https://jira.hyperledger.org/browse/FAB-3651) add getSignedProposal() API
* [8c2352a](https://github.com/hyperledger/fabric-chaincode-java/commit/8c2352a) [FAB-6494](https://jira.hyperledger.org/browse/FAB-6494) Add unit tests for ChaincodeStubImpl
* [b58bcc2](https://github.com/hyperledger/fabric-chaincode-java/commit/b58bcc2) Update Jim's RC ID in MAINTAINERS.rst
* [02520ac](https://github.com/hyperledger/fabric-chaincode-java/commit/02520ac) Initial MAINTAINERS file
* [915824f](https://github.com/hyperledger/fabric-chaincode-java/commit/915824f) [FAB-6435](https://jira.hyperledger.org/browse/FAB-6435) Copy Java shim from fabric repository
* [067b712](https://github.com/hyperledger/fabric-chaincode-java/commit/067b712) [FAB-5928](https://jira.hyperledger.org/browse/FAB-5928) Initial gradle build script
================================================
FILE: CODEOWNERS
================================================
# SPDX-License-Identifier: Apache-2.0
# Fabric Chaincode Java Maintainers
* @hyperledger/fabric-chaincode-java-maintainers
================================================
FILE: CODE_OF_CONDUCT.md
================================================
Code of Conduct Guidelines
==========================
Please review the Hyperledger [Code of
Conduct](https://wiki.hyperledger.org/community/hyperledger-project-code-of-conduct)
before participating. It is important that we keep things civil.
This work is licensed under a Creative Commons Attribution 4.0 International License.
================================================
FILE: COMPATIBILITY.md
================================================
# Support and Compatibility
Github is used for code base management and issue tracking.
## Summary of Compatibility
This table shows the summary of the compatibility of the Java chaincode libraries, together with the JVM version they require.
| Java chaincode version | Minimum supported Java | Java runtime | Docker image platforms |
|------------------------|------------------------|--------------|------------------------|
| v1.4 | 8 | 8 | amd64 |
| v2.2 | 11 | 11 | amd64 |
| v2.5.0 - v2.5.4 | 11 | 11 | amd64, arm64 |
| v2.5.5 - v2.5.7 | 11 | 21 | amd64, arm64 |
| v2.5.8+ | 11 | 25 | amd64, arm64 |
The Java runtime provided by the chaincode Docker image determines the maximum Java version (and features) that smart contract code can exploit when using the default Java chaincode container.
Subject to a suitable runtime environment, the Java chaincode libraries can be used to communicate with Fabric peers at different LTS versions. The level of functionality is determined by the Fabric version in use and channel capabilities.
All Docker images, chaincode libraries and tools are tested using amd64 (x86-64) only.
## Chaincode builder
The default Fabric chaincode builder creates a Docker container to run deployed smart contracts. Java chaincode Docker containers are built using the `hyperledger/fabric-javaenv` Docker image, tagged with the same major and minor version as the Fabric peer version. For example, Fabric v2.5 creates Java chaincode containers using the `hyperledger/fabric-javaenv:2.5` Docker image. Fabric v3 continues to use the v2.5 Java chaincode image.
A different chaincode Docker image can be specified using the `CORE_CHAINCODE_JAVA_RUNTIME` environment variable on the Fabric peer. For example, `CORE_CHAINCODE_JAVA_RUNTIME=example/customJavaRuntime:latest`.
With Fabric v2 and later, an alternative chaincode builder can be configured on the Fabric peer. In this case the configured chaincode builder controls how chaincode is launched. See the [Fabric documentation](https://hyperledger-fabric.readthedocs.io/en/release-2.5/cc_launcher.html) for further details.
## Chaincode packaging
When using the `hyperledger/fabric-javaenv` Java chaincode Docker images, deployed chaincode is built as follows:
- If both Gradle and Maven files are present, Gradle is used.
- Gradle build files can be either Groovy or Kotlin.
- If Gradle or Maven wrappers are present, they will be used instead of the preinstalled Gradle or Maven versions.
Remember that when using the wrappers, code will be downloaded from the Internet. Keep this in mind for any installation with limited network access.
Alternatively, it is recommended to package prebuilt JAR files, including the smart contract and all dependencies. In this case, no Internet access is required when deploying Java chaincode.
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to fabric-chaincode-java
We welcome contributions to the [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io) Project. There's always plenty to do!
If you have any questions about the project or how to contribute, you can find us in the [fabric-contracts-api](https://discordapp.com/channels/905194001349627914/943090527920877598) channel on [Discord](https://discord.lfdecentralizedtrust.org/).
Here are a few guidelines to help you contribute successfully...
## Issues
All issues are tracked in the issues tab in GitHub. If you find a bug which we don't already know about, you can help us by creating a new issue describing the problem. Please include as much detail as possible to help us track down the cause.If you want to begin contributing code, looking through our open issues is a good way to start. Try looking for recent issues with detailed descriptions first, or ask us on Discord if you're unsure which issue to choose.
## Enhancements
Make sure you have the support of the Hyperledger Fabric community before investing a lot of effort in project enhancements. Please look up the [Fabric RFC](https://github.com/hyperledger/fabric-rfcs) process for large changes.
## Pull Requests
We use our own forks and [Github Flow](https://docs.github.com/en/get-started/using-github/github-flow) to deliver changes to the code. Follow these steps to deliver your first pull request:
1. [Fork the repository](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project) and create a new branch from `main`.
2. If you've added code that should be tested, add tests!
3. If you've added any new features or made breaking changes, update the documentation.
4. Ensure all the tests pass.
5. Include the JIRA issue number, a descriptive message, and the [Developer Certificate of Origin (DCO) sign-off](https://github.com/dcoapp/app#how-it-works) on all commit messages.
6. [Issue a pull request](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project#making-a-pull-request)!
7. [GitHub Actions](https://github.com/hyperledger/fabric-chaincode-java/actions) builds must succeed before the pull request can be reviewed and merged.
## Coding Style
Please to try to be consistent with the rest of the code and conform to checkstyle rules where they are provided. [Spotless](https://github.com/diffplug/spotless) is used to enforce code formatting. You can run `./gradlew spotlessApply` to apply the mandated code formatting to the codebase before submitting changes to avoid failing the build with formatting violations.
## Code of Conduct Guidelines
See our [Code of Conduct Guidelines](../blob/main/CODE_OF_CONDUCT.md).
## Maintainers
Should you have any questions or concerns, please reach out to one of the project's [Maintainers](../blob/main/MAINTAINERS.md).
## How to work with the Codebase
Some useful gradle commands to help with building. You can add or remove the `--no-daemon` as you wish; depending on the performance of you local machine.
```shell
# build everything
./gradlew --no-daemon build
# clean up to force tests and compile to rerun
./gradlew clean cleanTest
./gradlew --no-daemon :fabric-chaincode-shim:build
# build docker image
./gradlew :fabric-chaincode-docker:buildImage
```
You can also scan for vulnerabilities in dependencies (requires [Make](https://www.gnu.org/software/make/) and [Go](https://go.dev/) to be installed):
```shell
make scan
```
## Hyperledger Fabric
See the
[Hyperledger Fabric contributors guide](http://hyperledger-fabric.readthedocs.io/en/latest/CONTRIBUTING.html) for more details, including other Hyperledger Fabric projects you may wish to contribute to.
---
[](http://creativecommons.org/licenses/by/4.0/)
This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/)
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: MAINTAINERS.md
================================================
# Maintainers
| Name | GitHub | Chat | email |
| ------------ | ----------------------------------------------------- | --------------- | -------------------------- |
| Dave Enyeart | [denyeart](https://github.com/denyeart) | denyeart | |
| Mark Lewis | [bestbeforetoday](https://github.com/bestbeforetoday) | bestbeforetoday | |
# Retired Maintainers
| Name | GitHub | Chat | email |
| ----------------------- | ------------------------------------------------------- | ------------- | ------------------------------------- |
| Artem Barger | [c0rwin](https://github.com/c0rwin) | c0rwin | |
| Matthew B White | [mbwhite](https://github.com/mbwhite) | mbwhite | |
| James Taylor | [jt-nti](https://github.com/jt-nti) | jtonline | |
| Gari Singh | [mastersingh24](https://github.com/mastersingh24) | mastersingh24 | |
| Gennady Laventman | [gennadylaventman](https://github.com/gennadylaventman) | gennadyl | |
| Jim Zhang | [jimthematrix](https://github.com/jimthematrix) | jimthematrix | |
| Luis Sanchez | [sanchezl](https://github.com/sanchezl) | sanchezl | |
| Srinivasan Muralidharan | [muralisrini](https://github.com/muralisrini) | muralisr | |
| Yacov Manevich | [yacovm](https://github.com/yacovm) | yacovm | |
Also: Please see the [Release Manager section](https://github.com/hyperledger/fabric/blob/main/MAINTAINERS.md)
This work is licensed under a Creative Commons Attribution 4.0 International License.
================================================
FILE: Makefile
================================================
#
# SPDX-License-Identifier: Apache-2.0
#
bin_dir := bin
osv-scanner := $(bin_dir)/osv-scanner
kernel_name := $(shell uname -s | tr '[:upper:]' '[:lower:]')
machine_hardware := $(shell uname -m)
ifeq ($(machine_hardware), x86_64)
machine_hardware := amd64
endif
ifeq ($(machine_hardware), aarch64)
machine_hardware := arm64
endif
.PHONY: scan
scan: $(osv-scanner)
rm -f fabric-chaincode-shim/gradle.lockfile
./gradlew --quiet :fabric-chaincode-shim:dependencies --write-locks --configuration runtimeClasspath
bin/osv-scanner scan --lockfile=fabric-chaincode-shim/gradle.lockfile
.PHONY: scan-all
scan-all: $(osv-scanner)
rm -f fabric-chaincode-shim/gradle.lockfile
./gradlew --quiet :fabric-chaincode-shim:dependencies --write-locks
bin/osv-scanner scan --lockfile=fabric-chaincode-shim/gradle.lockfile
.PHONY: install-osv-scanner
install-osv-scanner:
mkdir -p '$(bin_dir)'
curl --fail --location --show-error --silent --output '$(osv-scanner)' \
'https://github.com/google/osv-scanner/releases/latest/download/osv-scanner_$(kernel_name)_$(machine_hardware)'
chmod u+x '$(osv-scanner)'
$(osv-scanner):
$(MAKE) install-osv-scanner
================================================
FILE: README.md
================================================
# Hyperledger Fabric Chaincode Java
[](https://dev.azure.com/Hyperledger/Fabric-Chaincode-Java/_build/latest?definitionId=39&branchName=main)
[](https://maven-badges.herokuapp.com/maven-central/org.hyperledger.fabric-chaincode-java/fabric-chaincode-shim)
[](https://discordapp.com/channels/905194001349627914/943090527920877598)
This is a Java based implementation of Hyperledger Fabric chaincode shim APIs, which enables development of smart contracts using the Java language.
This project creates `fabric-chaincode-shim` jar
files for developers' consumption and the `hyperledger/fabric-javaenv` docker image
to run Java chaincode.
## Getting Started
Application developers interested in developing Java smart contracts for Hyperledger Fabric should read the [JavaDoc](https://hyperledger.github.io/fabric-chaincode-java/) which includes download information, and links to documentation and samples.
## Project structure
### fabric-chaincode-shim
Contains the java shim classes that define Java chaincode API and way to communicate with Fabric peers.
### fabric-chaincode-docker
Contains instructions to build the `hyperledger/fabric-javaenv` docker image.
### fabric-chaincode-integration-test
Contains higher level tests for Java chaincode.
> **Note:** in the future these should be replaced with a separate suite of [Cucumber](https://cucumber.io) tests which run against all chaincode implementations.
### examples
The following technical examples are in this repository. Please see the tutorials in the [documentation](https://hyperledger-fabric.readthedocs.io/en/latest/tutorials.html)
- **fabric-contract-example-gradle** - Contains an example Java contract built using gradle
- **fabric-contract-example-maven** - Contains an example Java contract built using maven
- **fabric-contract-example-gradle-kotlin** - Contains an example Kotlin contract build using gradle (Kotlin gradle files)
- **fabric-chaincode-example-sacc** - Contains an example java chaincode gradle project that includes sample chaincode and basic gradle build instructions.
- **fabric-chaincode-example-sbe** - Contains an example java chaincode gradle project that includes state based endorsement
## 'dev' main branch builds
These 'dev' drivers are built from the main branch only, and have a version format including the date for example `2.3.1.dev.20210303`.
They are published to Artifactory. These can be accessed via the repository at
```
maven {
url "https://hyperledger.jfrog.io/hyperledger/fabric-maven"
}
```
They can be accessed in a build file like this
```
dependencies {
compile group: 'org.hyperledger.fabric-chaincode-java', name: 'fabric-chaincode-shim', version: '2.3.1.dev.+'
}
```
## Building and testing
Make sure you have the following prereqs installed:
- [Docker](https://www.docker.com/get-docker)
- [Docker Compose](https://docs.docker.com/compose/install/)
- [JDK 11](https://adoptium.net/)
> **Note:** Java can be installed using [sdkman](https://sdkman.io/).
Clone the repository if you haven't already.
```
git clone https://github.com/hyperledger/fabric-chaincode-java.git
```
Build java shim jars (proto and shim jars) and install them to local maven repository.
```
cd fabric-chaincode-java
./gradlew clean build install
```
> **Note:** `./gradlew clean build classes` can be used instead to reduce the binaries that are built. This should be sufficient for using the local repository.
Build javaenv docker image, to have it locally.
```
./gradlew buildImage
```
## Compatibility
For details on what Java runtime and versions of Hyperledger Fabric can be used please see the [compatibility document](COMPATIBILITY.md).
---
[](http://creativecommons.org/licenses/by/4.0/)
This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/)
================================================
FILE: RELEASING.md
================================================
# Releasing
The following artifacts are created as a result of releasing Fabric Chaincode Java:
- `fabric-javaenv` Docker images:
- [Docker Hub](https://hub.docker.com/r/hyperledger/fabric-javaenv)
- [GitHub Packages](https://github.com/orgs/hyperledger/packages/container/package/fabric-javaenv)
- `fabric-chaincode-shim` Java libraries:
- [Maven Central](https://central.sonatype.com/artifact/org.hyperledger.fabric-chaincode-java/fabric-chaincode-shim)
- [GitHub Packages](https://github.com/hyperledger/fabric-chaincode-java/packages/50049)
## Before releasing
The following tasks are required before releasing:
- Ensure the version number in `build.gradle` is the required release version.
- Check the last branch build passed since exactly this repository state will be released.
## Create release
Creating a GitHub release on the [releases page](https://github.com/hyperledger/fabric-chaincode-java/releases) will trigger the build to publish the new release.
When drafting the release, create a new tag for the new version (with a `v` prefix). For example: `v2.1.4`
See previous releases for examples of the title and description.
## After releasing
- Update the version number in `build.gradle` to the next version.
- Update image version numbers in `fabric-chaincode-docker/build.gradle` to match the next version.
- Update the `fabric-chaincode-shim` dependency version in all `build.gradle` and `pom.xml` files within `fabric-chaincode-integration-test/src/contracts` to match the next version.
- Update the `fabric-chaincode-shim` dependency version in all `build.gradle`, `build.gradle.kts` and `pom.xml` files within `examples` to match the last _released_ version.
- Check that `COMPATIBILITY.md` is correct and update if required.
================================================
FILE: SECURITY.md
================================================
# Hyperledger Security Policy
## Reporting a Security Bug
If you think you have discovered a security issue in any of the Hyperledger projects, we'd love to hear from you. We will take all security bugs seriously and if confirmed upon investigation we will patch it within a reasonable amount of time and release a public security bulletin discussing the impact and credit the discoverer.
There are two ways to report a security bug. The easiest is to email a description of the flaw and any related information (e.g. reproduction steps, version) to [security at hyperledger dot org](mailto:security@hyperledger.org).
The other way is to file a confidential security bug in our [JIRA bug tracking system](https://jira.hyperledger.org). Be sure to set the “Security Level” to “Security issue”.
The process by which the Hyperledger Security Team handles security bugs is documented further in our [Defect Response page](https://wiki.hyperledger.org/display/SEC/Defect+Response) on our [wiki](https://wiki.hyperledger.org).
================================================
FILE: build.gradle
================================================
/*
* Copyright IBM Corp. 2018 All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
plugins {
id "com.github.ben-manes.versions" version "0.54.0"
id "com.diffplug.spotless" version "8.4.0"
id "com.gradleup.nmcp.aggregation" version "1.4.4"
id "com.gradleup.nmcp" version "1.4.4" apply false
}
version = '2.5.9'
// If the nightly property is set, then this is the scheduled main
// build - and we should publish this to artifactory
//
// Use the .dev. format to match Maven convention
if (properties.containsKey('NIGHTLY')) {
version = version + '.dev.' + getDate()
ext.nightly = true // set property for use in subprojects
} else {
ext.nightly = false
}
nmcpAggregation {
centralPortal {
username = findProperty('mavenCentralUsername')
password = findProperty('mavenCentralPassword')
publishingType = "AUTOMATIC"
}
}
dependencies {
nmcpAggregation(project(':fabric-chaincode-shim'))
}
allprojects {
apply plugin: "com.diffplug.spotless"
repositories {
mavenCentral()
}
spotless {
format 'misc', {
target '*.gradle', '.gitattributes', '.gitignore'
trimTrailingWhitespace()
leadingTabsToSpaces()
endWithNewline()
}
}
}
subprojects {
apply plugin: 'java'
apply plugin: "maven-publish"
group = 'org.hyperledger.fabric-chaincode-java'
version = rootProject.version
compileJava {
options.release = 11
options.compilerArgs += ['-Werror', '-Xlint:all']
}
dependencies {
implementation 'commons-cli:commons-cli:1.11.0'
implementation 'commons-logging:commons-logging:1.3.6'
testImplementation platform('org.junit:junit-bom:6.0.3')
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.assertj:assertj-core:3.27.7'
testImplementation 'org.mockito:mockito-core:5.23.0'
testImplementation 'uk.org.webcompere:system-stubs-jupiter:2.1.8'
testImplementation 'org.hamcrest:hamcrest-library:3.0'
}
test {
useJUnitPlatform()
}
spotless {
java {
removeUnusedImports()
palantirJavaFormat().formatJavadoc(true)
formatAnnotations()
}
}
}
// Get the date in the reverse format for sorting
static def getDate() {
def date = new Date()
def formattedDate = date.format('yyyyMMdd')
return formattedDate
}
================================================
FILE: docs/404.md
================================================
---
title: "404 - Page Not Found"
permalink: /404.html
---
## The page you wanted does not exist
If you were looking for Javadoc, try one of the releases below:
{% include javadocs.html %}
================================================
FILE: docs/_config.yml
================================================
theme: minima
title: "fabric-chaincode-java"
releases:
- main
- release-1.4
- release-2.2
================================================
FILE: docs/_includes/footer.html
================================================
================================================
FILE: docs/_includes/header.html
================================================
{@code logger.setParent(java.util.logging.Logger.getLogger("org.hyperledger.fabric"))}
*
* @param name A name for the logger.
*/
protected Logger(final String name) {
super(name, null);
}
/**
* @param name
* @return Logger
*/
public static Logger getLogger(final String name) {
Logger result = new Logger(name);
result.setParent(java.util.logging.Logger.getLogger("org.hyperledger.fabric"));
return result;
}
/** @param msgSupplier */
public void debug(final Supplier msgSupplier) {
log(Level.FINEST, msgSupplier);
}
/** @param msg */
public void debug(final String msg) {
log(Level.FINEST, msg);
}
/**
* @param class1
* @return Logger
*/
public static Logger getLogger(final Class> class1) {
// important to add the logger to the log manager
final Logger result = Logger.getLogger(class1.getName());
LogManager.getLogManager().addLogger(result);
return result;
}
/** @param message */
public void error(final String message) {
log(Level.SEVERE, message);
}
/** @param msgSupplier */
public void error(final Supplier msgSupplier) {
log(Level.SEVERE, msgSupplier);
}
/**
* @param throwable
* @return Throwable
*/
public String formatError(final Throwable throwable) {
if (throwable == null) {
return null;
}
final StringWriter buffer = new StringWriter();
buffer.append(throwable.getMessage());
throwable.printStackTrace(new PrintWriter(buffer));
final Throwable cause = throwable.getCause();
if (cause != null) {
buffer.append(".. caused by ..");
buffer.append(this.formatError(cause));
}
return buffer.toString();
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/Logging.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.LogManager;
/**
* Assistance class to use when logging.
*
*
For chaincode/contract implementations please use java.util.logging or your own framework. All the Hyperledger
* Fabric code here is logged in loggers with names starting org.hyperledger
*
*
Control of this is via the environment variables 'CORE_CHAINCODE_LOGGING_LEVEL' this takes a string that matches
* the following Java.util.logging levels (case insensitive)
*
*
CRITICAL, ERROR == Level.SEVERE, WARNING == Level.WARNING, INFO == Level.INFO NOTICE == Level.CONFIG, DEBUG ==
* Level.FINEST
*/
public final class Logging {
/** Name of the Performance logger. */
public static final String PERFLOGGER = "org.hyperledger.Performance";
/** Private Constructor. */
private Logging() {}
/**
* Formats a Throwable to a string with details of all the causes.
*
* @param throwable Exception
* @return String formatted with all the details
*/
public static String formatError(final Throwable throwable) {
if (throwable == null) {
return null;
}
final StringWriter buffer = new StringWriter();
buffer.append(throwable.getMessage()).append(System.lineSeparator());
throwable.printStackTrace(new PrintWriter(buffer));
final Throwable cause = throwable.getCause();
if (cause != null) {
buffer.append(".. caused by ..").append(System.lineSeparator());
buffer.append(formatError(cause));
}
return buffer.toString();
}
/**
* Sets the log level to the the.
*
* @param newLevel the new logging level
*/
public static void setLogLevel(final String newLevel) {
final Level l = mapLevel(newLevel);
final LogManager logManager = LogManager.getLogManager();
// slightly cumbersome approach - but the loggers don't have a 'get children'
// so find those that have the correct stem.
final List allLoggers = Collections.list(logManager.getLoggerNames());
allLoggers.add("org.hyperledger");
allLoggers.stream()
.filter(name -> name.startsWith("org.hyperledger"))
.map(logManager::getLogger)
.forEach(logger -> {
if (logger != null) {
logger.setLevel(l);
}
});
}
private static Level mapLevel(final String level) {
if (level != null) {
switch (level.toUpperCase(Locale.getDefault()).trim()) {
case "ERROR":
case "CRITICAL":
return Level.SEVERE;
case "WARNING":
case "WARN":
return Level.WARNING;
case "INFO":
return Level.INFO;
case "NOTICE":
return Level.CONFIG;
case "DEBUG":
return Level.FINEST;
default:
return Level.INFO;
}
}
return Level.INFO;
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ClientIdentity.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DEROctetString;
import org.hyperledger.fabric.Logger;
import org.hyperledger.fabric.protos.msp.SerializedIdentity;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.json.JSONException;
import org.json.JSONObject;
/**
* ClientIdentity represents information about the identity that submitted a transaction. Chaincodes can use this class
* to obtain information about the submitting identity including a unique ID, the MSP (Membership Service Provider) ID,
* and attributes. Such information is useful in enforcing access control by the chaincode.
*/
public final class ClientIdentity {
private static final Logger LOGGER = Logger.getLogger(ContractRouter.class.getName());
private final String mspId;
private final X509Certificate cert;
private final Map attrs;
private final String id;
// special OID used by Fabric to save attributes in x.509 certificates
private static final String FABRIC_CERT_ATTR_OID = "1.2.3.4.5.6.7.8.1";
/**
* Creates new ClientIdentity helper.
*
* @param stub
* @throws CertificateException
* @throws JSONException
* @throws IOException
*/
public ClientIdentity(final ChaincodeStub stub) throws CertificateException, IOException {
final byte[] signingId = stub.getCreator();
// Create a Serialized Identity protobuf
final SerializedIdentity si = SerializedIdentity.parseFrom(signingId);
this.mspId = si.getMspid();
final byte[] idBytes = si.getIdBytes().toByteArray();
final X509Certificate cert = (X509Certificate)
CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(idBytes));
this.cert = cert;
// Get the extension where the identity attributes are stored
final byte[] extensionValue = cert.getExtensionValue(FABRIC_CERT_ATTR_OID);
if (extensionValue != null) {
this.attrs = parseAttributes(extensionValue);
} else {
this.attrs = new HashMap<>();
}
// Populate identity
this.id = "x509::" + cert.getSubjectDN().getName() + "::"
+ cert.getIssuerDN().getName();
}
/**
* getId returns the ID associated with the invoking identity. This ID is guaranteed to be unique within the MSP.
*
* @return {String} A string in the format: "x509::{subject DN}::{issuer DN}"
*/
public String getId() {
return this.id;
}
/**
* getMSPID returns the MSP ID of the invoking identity.
*
* @return {String}
*/
public String getMSPID() {
return this.mspId;
}
/**
* parseAttributes returns a map of the attributes associated with an identity.
*
* @param extensionValue DER-encoded Octet string stored in the attributes extension of the certificate, as a byte
* array
* @return attrMap {Map} a map of identity attributes as key value pair strings
* @throws IOException
*/
private Map parseAttributes(final byte[] extensionValue) throws IOException {
final Map attrMap = new HashMap<>();
// Create ASN1InputStream from extensionValue
try (ByteArrayInputStream inStream = new ByteArrayInputStream(extensionValue);
ASN1InputStream asn1InputStream = new ASN1InputStream(inStream)) {
// Read the DER object
final ASN1Primitive derObject = asn1InputStream.readObject();
if (derObject instanceof DEROctetString) {
final DEROctetString derOctetString = (DEROctetString) derObject;
// Create attributeString from octets and create JSON object
final String attributeString = new String(derOctetString.getOctets(), UTF_8);
final JSONObject extJSON = new JSONObject(attributeString);
final JSONObject attrs = extJSON.getJSONObject("attrs");
final Iterator keys = attrs.keys();
while (keys.hasNext()) {
final String key = keys.next();
// Populate map with attributes and values
attrMap.put(key, attrs.getString(key));
}
}
} catch (final JSONException error) {
// creating a JSON object failed
// decoded extensionValue is not a string containing JSON
LOGGER.error(() -> LOGGER.formatError(error));
// return empty map
}
return attrMap;
}
/**
* getAttributeValue returns the value of the client's attribute named `attrName`. If the invoking identity
* possesses the attribute, returns the value of the attribute. If the invoking identity does not possess the
* attribute, returns null.
*
* @param attrName Name of the attribute to retrieve the value from the identity's credentials (such as x.509
* certificate for PKI-based MSPs).
* @return {String | null} Value of the attribute or null if the invoking identity does not possess the attribute.
*/
public String getAttributeValue(final String attrName) {
return this.attrs.getOrDefault(attrName, null);
}
/**
* assertAttributeValue verifies that the invoking identity has the attribute named `attrName` with a value of
* `attrValue`.
*
* @param attrName Name of the attribute to retrieve the value from the identity's credentials (such as x.509
* certificate for PKI-based MSPs)
* @param attrValue Expected value of the attribute
* @return {boolean} True if the invoking identity possesses the attribute and the attribute value matches the
* expected value. Otherwise, returns false.
*/
public boolean assertAttributeValue(final String attrName, final String attrValue) {
return this.attrs.containsKey(attrName) && attrValue.equals(this.attrs.get(attrName));
}
/**
* getX509Certificate returns the X509 certificate associated with the invoking identity, or null if it was not
* identified by an X509 certificate, for instance if the MSP is implemented with an alternative to PKI such as
* [Identity Mixer](https://jira.hyperledger.org/browse/FAB-5673).
*
* @return {X509Certificate | null}
*/
public X509Certificate getX509Certificate() {
return this.cert;
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/Context.java
================================================
/*
* Copyright 2019 IBM DTCC All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract;
import java.io.IOException;
import java.security.cert.CertificateException;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.json.JSONException;
/**
* This context is available to all 'transaction functions' and provides the transaction context. It also provides
* access to the APIs for the world state using {@link #getStub()}
*
*
Applications can implement their own versions if they wish to add functionality. All subclasses MUST implement a
* constructor, for example
*
*
*/
public class Context {
/** */
protected ChaincodeStub stub;
/** */
protected ClientIdentity clientIdentity;
/**
* Creates new client identity and sets it as a property of the stub.
*
* @param stub Instance of the {@link ChaincodeStub} to use
*/
public Context(final ChaincodeStub stub) {
this.stub = stub;
try {
this.clientIdentity = new ClientIdentity(stub);
} catch (CertificateException | JSONException | IOException e) {
throw new ContractRuntimeException("Could not create new client identity", e);
}
}
/** @return ChaincodeStub instance to use */
public ChaincodeStub getStub() {
return this.stub;
}
/** @return ClientIdentity object to use */
public ClientIdentity getClientIdentity() {
return this.clientIdentity;
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContextFactory.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract;
import org.hyperledger.fabric.shim.ChaincodeStub;
/** Factory to create {@link Context} from {@link ChaincodeStub} by wrapping stub with dynamic proxy. */
public final class ContextFactory {
private static final ContextFactory INSTANCE = new ContextFactory();
/** @return ContextFactory */
public static ContextFactory getInstance() {
return INSTANCE;
}
/**
* @param stub
* @return Context
*/
public Context createContext(final ChaincodeStub stub) {
return new Context(stub);
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractInterface.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract;
import org.hyperledger.fabric.shim.ChaincodeException;
import org.hyperledger.fabric.shim.ChaincodeStub;
/**
* All Contracts should implement this interface, in addition to the
* {@linkplain org.hyperledger.fabric.contract.annotation.Contract} annotation.
*
*
All methods on this interface have default implementations; for many contracts it may not be needed to sub-class
* these.
*
*
Each method on the Contract that is marked with the {@link org.hyperledger.fabric.contract.annotation.Transaction}
* annotation is considered a Transaction Function. This is eligible for calling. Each transaction function is supplied
* with its first parameter being a {@link org.hyperledger.fabric.contract.Context}. The other parameters are supplied
* at the developer's discretion.
*
*
The sequence of calls is
*
*
* createContext() -> beforeTransaction() -> the transaction function -> afterTransaction()
*
*
*
If any of these functions throws an exception it is considered an error case and the whole transaction is failed.
* The {@link org.hyperledger.fabric.contract.Context} is a very important object as it provides transactional context
* for access to current transaction id, ledger state, etc.
*
*
Note on Threading
*
*
All code should be 'Thread Friendly'. Each method must not rely on instance fields or class side variables for
* storage. Nor should they use any ThreadLocal Storage. Ledger data is stored via the ledger api available via the
* {@link Context}.
*
*
If information needs to be passed from {@link #beforeTransaction(Context)} to {@link #afterTransaction(Context,
* Object)} or between separate transaction functions when called directly then a subclass of the {@link Context} should
* be provided.
*/
public interface ContractInterface {
/**
* Create context from {@link ChaincodeStub}.
*
*
Default impl provided, but can be overwritten by contract
*
* @param stub Instance of the ChaincodeStub to use for this transaction
* @return instance of the context to use for the current transaction being executed
*/
default Context createContext(final ChaincodeStub stub) {
return ContextFactory.getInstance().createContext(stub);
}
/**
* Invoked for any transaction that does not exist.
*
*
This will throw an exception. If you wish to alter the exception thrown or if you wish to consider requests
* for transactions that don't exist as not an error, subclass this method.
*
* @param ctx the context as created by {@link #createContext(ChaincodeStub)}.
*/
default void unknownTransaction(final Context ctx) {
throw new ChaincodeException("Undefined contract method called");
}
/**
* Invoked once before each transaction.
*
*
Any exceptions thrown will fail the transaction, and neither the required transaction or the
* {@link #afterTransaction(Context, Object)} will be called
*
* @param ctx the context as created by {@link #createContext(ChaincodeStub)}.
*/
default void beforeTransaction(final Context ctx) {
// Nothing by default
}
/**
* Invoked once after each transaction.
*
*
Any exceptions thrown will fail the transaction.
*
* @param ctx the context as created by {@link #createContext(ChaincodeStub)}.
* @param result The object returned from the transaction function if any. As this is a Java object and therefore
* pass-by-reference it is possible to modify this object.
*/
default void afterTransaction(final Context ctx, final Object result) {
// Nothing by default
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRouter.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;
import org.hyperledger.fabric.Logging;
import org.hyperledger.fabric.contract.execution.ExecutionFactory;
import org.hyperledger.fabric.contract.execution.ExecutionService;
import org.hyperledger.fabric.contract.execution.InvocationRequest;
import org.hyperledger.fabric.contract.metadata.MetadataBuilder;
import org.hyperledger.fabric.contract.routing.ContractDefinition;
import org.hyperledger.fabric.contract.routing.RoutingRegistry;
import org.hyperledger.fabric.contract.routing.TxFunction;
import org.hyperledger.fabric.contract.routing.TypeRegistry;
import org.hyperledger.fabric.contract.routing.impl.RoutingRegistryImpl;
import org.hyperledger.fabric.contract.routing.impl.SerializerRegistryImpl;
import org.hyperledger.fabric.metrics.Metrics;
import org.hyperledger.fabric.shim.ChaincodeBase;
import org.hyperledger.fabric.shim.ChaincodeServer;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.NettyChaincodeServer;
import org.hyperledger.fabric.shim.ResponseUtils;
import org.hyperledger.fabric.traces.Traces;
/**
* Router class routes Init/Invoke requests to contracts. Implements {@link org.hyperledger.fabric.shim.Chaincode}
* interface.
*
* @see ContractInterface
*/
public final class ContractRouter extends ChaincodeBase {
private static final Logger LOGGER = Logger.getLogger(ContractRouter.class.getName());
private final RoutingRegistry registry;
private final TypeRegistry typeRegistry;
// Store instances of SerializerInterfaces - identified by the contract
// annotation (default is JSON)
private final SerializerRegistryImpl serializers;
private final ExecutionService executor;
/**
* Take the arguments from the cli, and initiate processing of cli options and environment variables.
*
*
Create the Contract scanner, and the Execution service
*
* @param args
*/
public ContractRouter(final String[] args) {
super();
super.initializeLogging();
super.processEnvironmentOptions();
super.processCommandLineOptions(args);
super.validateOptions();
final Properties props = super.getChaincodeConfig();
Metrics.initialize(props);
Traces.initialize(props);
LOGGER.fine("ContractRouter");
registry = new RoutingRegistryImpl();
typeRegistry = TypeRegistry.getRegistry();
serializers = new SerializerRegistryImpl();
try {
serializers.findAndSetContents();
} catch (InstantiationException | IllegalAccessException e) {
final ContractRuntimeException cre = new ContractRuntimeException("Unable to locate Serializers", e);
LOGGER.severe(() -> Logging.formatError(cre));
throw cre;
}
executor = ExecutionFactory.getInstance().createExecutionService(serializers);
}
/** Locate all the contracts that are available on the classpath. */
void findAllContracts() {
registry.findAndSetContracts(this.typeRegistry);
}
/**
* Start the chaincode container off and running.
*
*
This will send the initial flow back to the peer
*
* @throws Exception
*/
@SuppressWarnings("PMD.AvoidCatchingGenericException")
void startRouting() {
try {
super.connectToPeer();
} catch (final Exception e) {
LOGGER.severe(() -> Logging.formatError(e));
throw new ContractRuntimeException("Unable to start routing", e);
}
}
@SuppressWarnings("PMD.AvoidCatchingGenericException")
private Response processRequest(final ChaincodeStub stub) {
LOGGER.info(() -> "Got invoke routing request");
try {
if (stub.getStringArgs().isEmpty()) {
return ResponseUtils.newSuccessResponse();
}
LOGGER.info(() -> "Got the invoke request for:" + stub.getFunction() + " " + stub.getParameters());
final InvocationRequest request = ExecutionFactory.getInstance().createRequest(stub);
final TxFunction txFn = getRouting(request);
LOGGER.info(() -> "Got routing:" + txFn.getRouting());
return executor.executeRequest(txFn, request, stub);
} catch (final Throwable throwable) {
return ResponseUtils.newErrorResponse(throwable);
}
}
@Override
public Response invoke(final ChaincodeStub stub) {
return processRequest(stub);
}
@Override
public Response init(final ChaincodeStub stub) {
return processRequest(stub);
}
/**
* Given the Invocation Request, return the routing object for this call.
*
* @param request
* @return TxFunction for the request
*/
TxFunction getRouting(final InvocationRequest request) {
// request name is the fully qualified 'name:txname'
if (registry.containsRoute(request)) {
return registry.getTxFn(request);
} else {
LOGGER.fine(() -> "Namespace is " + request);
final ContractDefinition contract = registry.getContract(request.getNamespace());
return contract.getUnknownRoute();
}
}
/**
* Main method to start the contract based chaincode.
*
* @param args
*/
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public static void main(final String[] args) throws Exception {
final ContractRouter cfc = new ContractRouter(args);
cfc.findAllContracts();
LOGGER.fine(() -> cfc.getRoutingRegistry().toString());
// Create the Metadata ahead of time rather than have to produce every
// time
MetadataBuilder.initialize(cfc.getRoutingRegistry(), cfc.getTypeRegistry());
LOGGER.info(() -> "Metadata follows:" + MetadataBuilder.debugString());
// check if this should be running in client or server mode
if (cfc.isServer()) {
LOGGER.info("Starting chaincode as server");
ChaincodeServer chaincodeServer = new NettyChaincodeServer(cfc, cfc.getChaincodeServerConfig());
chaincodeServer.start();
} else {
LOGGER.info("Starting chaincode as client");
cfc.startRouting();
}
}
TypeRegistry getTypeRegistry() {
return this.typeRegistry;
}
RoutingRegistry getRoutingRegistry() {
return this.registry;
}
/**
* Start router and Chaincode server.
*
* @param chaincodeServer
*/
public void startRouterWithChaincodeServer(final ChaincodeServer chaincodeServer)
throws IOException, InterruptedException {
findAllContracts();
LOGGER.fine(() -> getRoutingRegistry().toString());
MetadataBuilder.initialize(getRoutingRegistry(), getTypeRegistry());
LOGGER.info(() -> "Metadata follows:" + MetadataBuilder.debugString());
chaincodeServer.start();
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContractRuntimeException.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract;
import org.hyperledger.fabric.shim.ChaincodeException;
/**
* Specific RuntimeException for events that occur in the calling and handling of the Contracts, NOT within the contract
* logic itself.
*
*
FUTURE At some future point we wish to add more diagnostic information into this, for example current tx id
*/
public class ContractRuntimeException extends ChaincodeException {
/** Generated serial version id. */
private static final long serialVersionUID = -884373036398750450L;
/** @param string */
public ContractRuntimeException(final String string) {
super(string);
}
/**
* @param string
* @param cause
*/
public ContractRuntimeException(final String string, final Throwable cause) {
super(string, cause);
}
/** @param cause */
public ContractRuntimeException(final Throwable cause) {
super(cause);
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contact.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Class level annotation that identifies this class as being a contact. Can be populated with email, name and url
* fields.
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Contact {
/** @return String */
String email() default "";
/** @return String */
String name() default "";
/** @return String */
String url() default "";
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Contract.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Class level annotation that identifies this class as being a contract. Can supply information and an alternative name
* for the contract rather than the classname
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Contract {
/**
* The Info object can be supplied to provide additional information about the contract.
*
*
Including title, description, version and license
*
* @return Info object
*/
Info info() default @Info();
/**
* Contract name.
*
*
Normally the name of the class is used to refer to the contract (name without package). This can be altered if
* wished.
*
* @return Name of the contract to be used instead of the Classname
*/
String name() default "";
/**
* Transaction Serializer Classname.
*
*
Fully Qualified Classname of the TRANSACTION serializer that should be used with this contract.
*
*
This is the serializer that is used to parse incoming transaction request parameters and convert the return
* type
*
* @return Default serializer classname
*/
String transactionSerializer() default "org.hyperledger.fabric.contract.execution.JSONTransactionSerializer";
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/DataType.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Class level annotation indicating this class represents one of the complex types that can be returned or passed to
* the transaction functions.
*
*
These datatypes are used (within the current implementation) for determining the data flow protocol from the
* Contracts to the SDK and for permitting a fully formed Interface Definition to be created for the contract.
*
*
Complex types can appear within this definition, and these are identified using this annotation.
*
*
FUTURE To take these annotations are also utilize them for leverage storage
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface DataType {
/**
* Namespace of the type.
*
* @return String
*/
String namespace() default "";
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Default.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Default Contract.
*
*
Class level annotation that defines the contract that is the default contract, and as such invoke of the
* transaction functions does not need to be qualified by the contract name
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Default {}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Info.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Info Details
*
*
Class level annotation that identifies this class as being an info object. Can supply additional information about
* the contract, including title, description, version, license and contact information.
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Info {
/** @return String */
String title() default "";
/** @return String */
String description() default "";
/** @return String */
String version() default "";
/** @return String */
String termsOfService() default "";
/**
* License object that can be populated to include name and url.
*
* @return License object
*/
License license() default @License();
/**
* Contact object that can be populated with email, name and url fields.
*
* @return Contact object
*/
Contact contact() default @Contact();
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/License.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Class level annotation that identifies this class as being a license object. Can be populated to include name and
* url.
*/
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface License {
/** @return String */
String name() default "";
/** @return String */
String url() default "";
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Property.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Field and parameter level annotation defining a property of the class.
*
*
(identified by {@link DataType}) Can also be used on the parameters of transaction functions
*
*
Example of using this annotation
*
*
*
* // max 15 character string, a-z with spaces
* @Property(schema = {"pattern", "^[a-zA-Z\\s]{0,15}$"})
* private String text;
*
* // How friendly is this on a scale of 1-5, 1 being formal, 5 being familiar
* @Property(schema = {"minimum", "1", "maximum", "5"})
* private int friendliness = 1;
*
*
*/
@Retention(RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface Property {
/**
* Allows each property to be defined a detail set of rules to determine the valid types of this data. The format
* follows the syntax of the OpenAPI Schema object.
*
* @return String array of the key-value pairs of the schema
*/
String[] schema() default {};
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Serializer.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Class level annotation that defines the serializer that should be used to convert objects to and from the wire
* format.
*
*
This should annotate a class that implements the Serializer interface
*/
@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.TYPE_USE})
public @interface Serializer {
/** What is this serializer able to target? */
enum TARGET {
/** Target transaction functions. */
TRANSACTION,
/** Target all elements. */
ALL
}
/** @return Target of the serializer */
TARGET target() default Serializer.TARGET.ALL;
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/Transaction.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.annotation;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Method level annotation indicating the method to be a callable transaction function.
*
*
These functions are called in client SDKs by the combination of
*
*
* [contractname]:[transactioname]
*
*
* Unless specified otherwise, the contract name is the class name (without package) and the transaction name is the
* method name.
*/
@Retention(RUNTIME)
@Target(METHOD)
public @interface Transaction {
/** The intended invocation style for a transaction function. */
enum TYPE {
/** Transaction is used to submit updates to the ledger. */
SUBMIT,
/** Transaction is evaluated to query information from the ledger. */
EVALUATE
}
/**
* Submit semantics.
*
*
TRUE indicates that this function is intended to be called with the 'submit' semantics
*
*
FALSE indicates that this is intended to be called with the evaluate semantics
*
* @return boolean, default is true
* @deprecated Please use intent
*/
@Deprecated
boolean submit() default true;
/**
* What are submit semantics for this transaction.
*
*
*
SUBMIT
*
indicates that this function is intended to be called with the 'submit' semantics
*
EVALUATE
*
indicates that this is intended to be called with the 'evaluate' semantics
*
*
* @return submit semantics
*/
TYPE intent() default Transaction.TYPE.SUBMIT;
/**
* The name of the callable transaction if it should be different to the method name.
*
* @return the transaction name
*/
String name() default "";
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/annotation/package-info.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* Provides annotations required for Contract implementations.
*
* @see org.hyperledger.fabric.contract.ContractInterface
*/
package org.hyperledger.fabric.contract.annotation;
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionFactory.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.execution;
import org.hyperledger.fabric.contract.execution.impl.ContractExecutionService;
import org.hyperledger.fabric.contract.execution.impl.ContractInvocationRequest;
import org.hyperledger.fabric.contract.routing.impl.SerializerRegistryImpl;
import org.hyperledger.fabric.shim.ChaincodeStub;
public class ExecutionFactory {
private static final ExecutionFactory INSTANCE = new ExecutionFactory();
/** @return ExecutionFactory */
public static ExecutionFactory getInstance() {
return INSTANCE;
}
/**
* @param context Chaincode Context
* @return Invocation request
*/
public InvocationRequest createRequest(final ChaincodeStub context) {
return new ContractInvocationRequest(context);
}
/**
* @param serializers Instance of the serializer
* @return Execution Service
*/
public ExecutionService createExecutionService(final SerializerRegistryImpl serializers) {
return new ContractExecutionService(serializers);
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/ExecutionService.java
================================================
/*
* Copyright 2019 IBM DTCC All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.execution;
import org.hyperledger.fabric.contract.routing.TxFunction;
import org.hyperledger.fabric.shim.Chaincode;
import org.hyperledger.fabric.shim.ChaincodeStub;
/**
* ExecutionService.
*
*
Service that executes {@link InvocationRequest} (wrapped Init/Invoke + extra data) using routing information
*/
@FunctionalInterface
public interface ExecutionService {
/**
* @param txFn
* @param req
* @param stub
* @return Chaincode response
*/
Chaincode.Response executeRequest(TxFunction txFn, InvocationRequest req, ChaincodeStub stub);
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/InvocationRequest.java
================================================
/*
* Copyright 2019 IBM DTCC All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.execution;
import java.util.List;
/**
* Invocation Request.
*
*
All information needed to find {@link org.hyperledger.fabric.contract.annotation.Contract} and invoke the request.
*/
public interface InvocationRequest {
/** */
String DEFAULT_NAMESPACE = "default";
/** @return Namespace */
String getNamespace();
/** @return Method */
String getMethod();
/** @return Args as byte array */
List getArgs();
/** @return Request */
String getRequestName();
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/JSONTransactionSerializer.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.execution;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Set;
import org.hyperledger.fabric.Logger;
import org.hyperledger.fabric.contract.ContractRuntimeException;
import org.hyperledger.fabric.contract.annotation.Serializer;
import org.hyperledger.fabric.contract.metadata.TypeSchema;
import org.hyperledger.fabric.contract.routing.DataTypeDefinition;
import org.hyperledger.fabric.contract.routing.PropertyDefinition;
import org.hyperledger.fabric.contract.routing.TypeRegistry;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/** Used as the default serialisation for transmission from SDK to Contract. */
@Serializer()
@SuppressWarnings({
"PMD.GodClass",
"PMD.AvoidLiteralsInIfCondition",
"PMD.AvoidDuplicateLiterals",
"PMD.AvoidDeeplyNestedIfStmts"
})
public class JSONTransactionSerializer implements SerializerInterface {
private static final Logger LOGGER = Logger.getLogger(JSONTransactionSerializer.class.getName());
private final TypeRegistry typeRegistry = TypeRegistry.getRegistry();
/**
* Convert the value supplied to a byte array, according to the TypeSchema.
*
* @param value
* @param ts
* @return Byte buffer
*/
@Override
public byte[] toBuffer(final Object value, final TypeSchema ts) {
LOGGER.debug(() -> "Schema to convert is " + ts);
byte[] buffer = null;
if (value != null) {
final String type = ts.getType();
if (type != null) {
switch (type) {
case "array":
final JSONArray array = normalizeArray(new JSONArray(value), ts);
buffer = array.toString().getBytes(UTF_8);
break;
case "string":
final String format = ts.getFormat();
if ("utin16".equals(format)) {
buffer = Character.valueOf((char) value).toString().getBytes(UTF_8);
} else {
buffer = ((String) value).getBytes(UTF_8);
}
break;
case "number":
case "integer":
case "boolean":
default:
buffer = value.toString().getBytes(UTF_8);
}
} else {
// at this point we can assert that the value is
// representing a complex data type
// so we can get this from
// the type registry, and get the list of propertyNames
// it should have
final DataTypeDefinition dtd = this.typeRegistry.getDataType(ts);
final Set keySet = dtd.getProperties().keySet();
final String[] propNames = keySet.toArray(new String[0]);
// Note: whilst the current JSON library does pretty much
// everything is required, this part is hard.
// we want to create a JSON Object based on the value,
// with certain property names.
// Based on the constructors available we need to have a two
// step process, create a JSON Object, then create the object
// we really want based on the propNames
final JSONObject obj = new JSONObject(new JSONObject(value), propNames);
buffer = obj.toString().getBytes(UTF_8);
}
}
return buffer;
}
/**
* Normalize the Array.
*
*
We need to take the JSON array, and if there are complex datatypes within it ensure that they don't get
* spurious JSON properties appearing
*
*
This method needs to be general so has to copy with nested arrays and with primitive and Object types
*
* @param jsonArray incoming array
* @param ts Schema to normalise to
* @return JSONArray
*/
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
private JSONArray normalizeArray(final JSONArray jsonArray, final TypeSchema ts) {
JSONArray normalizedArray;
// Need to work with what type of array this is
final TypeSchema items = ts.getItems();
final String type = items.getType();
if (null == type) {
// get the permitted propeties in the type,
// then loop over the array and ensure they are correct
final DataTypeDefinition dtd = this.typeRegistry.getDataType(items);
final Set keySet = dtd.getProperties().keySet();
final String[] propNames = keySet.toArray(new String[0]);
normalizedArray = new JSONArray();
// array of objects
// iterate over said array
for (int i = 0; i < jsonArray.length(); i++) {
final JSONObject obj = new JSONObject(jsonArray.getJSONObject(i), propNames);
normalizedArray.put(i, obj);
}
} else if ("array".equals(type)) {
// nested arrays, get the type of what it makes up
// Need to loop over all elements and normalize each one
normalizedArray = new JSONArray();
for (int i = 0; i < jsonArray.length(); i++) {
normalizedArray.put(i, normalizeArray(jsonArray.getJSONArray(i), items));
}
} else {
// primitive - can return this directly
normalizedArray = jsonArray;
}
return normalizedArray;
}
/**
* Take the byte buffer and return the object as required.
*
* @param buffer Byte buffer from the wire
* @param ts TypeSchema representing the type
* @return Object created; relies on Java auto-boxing for primitives
*/
@Override
public Object fromBuffer(final byte[] buffer, final TypeSchema ts) {
try {
final String stringData = new String(buffer, UTF_8);
return convert(stringData, ts);
} catch (InstantiationException | IllegalAccessException e) {
throw new ContractRuntimeException(e);
}
}
/**
* We need to be able to map between the primative class types and the object variants. In the case where this is
* needed Java auto-boxing doesn't actually help.
*
*
For other types the parameter is passed directly back
*
* @param primitive class for the primitive
* @return Class for the Object variant
*/
private Class> mapPrimitive(final Class> primitive) {
if (primitive.isArray()) {
return mapArrayPrimitive(primitive);
}
return mapBasicPrimitive(primitive);
}
private Class> mapArrayPrimitive(final Class> primitive) {
switch (primitive.getComponentType().getName()) {
case "int":
return Integer[].class;
case "long":
return Long[].class;
case "float":
return Float[].class;
case "double":
return Double[].class;
case "short":
return Short[].class;
case "byte":
return Byte[].class;
case "char":
return Character[].class;
case "boolean":
return Boolean[].class;
default:
return primitive;
}
}
private Class> mapBasicPrimitive(final Class> primitive) {
switch (primitive.getName()) {
case "int":
return Integer.class;
case "long":
return Long.class;
case "float":
return Float.class;
case "double":
return Double.class;
case "short":
return Short.class;
case "byte":
return Byte.class;
case "char":
return Character.class;
case "boolean":
return Boolean.class;
default:
return primitive;
}
}
/** Internal method to do the conversion */
private Object convert(final String stringData, final TypeSchema ts)
throws IllegalAccessException, InstantiationException {
LOGGER.debug(() -> "Schema to convert is " + ts);
String type = ts.getType();
String format = null;
if (type == null) {
type = "object";
final String ref = ts.getRef();
format = ref.substring(ref.lastIndexOf('/') + 1);
}
switch (type) {
case "string":
return convertString(stringData, ts);
case "integer":
return convertInteger(stringData, ts);
case "number":
return convertNumber(stringData, ts);
case "boolean":
return Boolean.parseBoolean(stringData);
case "object":
return createComponentInstance(format, stringData, ts);
case "array":
return convertArray(stringData, ts);
default:
return null;
}
}
private Object convertArray(final String stringData, final TypeSchema ts)
throws IllegalAccessException, InstantiationException {
final JSONArray jsonArray = new JSONArray(stringData);
final TypeSchema itemSchema = ts.getItems();
// note here that the type has to be converted in the case of primitives
final Object[] data = (Object[])
Array.newInstance(mapPrimitive(itemSchema.getTypeClass(this.typeRegistry)), jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
final Object convertedData = convert(jsonArray.get(i).toString(), itemSchema);
data[i] = convertedData;
}
return data;
}
private Object convertNumber(final String stringData, final TypeSchema ts) {
if ("float".equals(ts.getFormat())) {
return Float.parseFloat(stringData);
}
return Double.parseDouble(stringData);
}
private Object convertInteger(final String stringData, final TypeSchema ts) {
switch (ts.getFormat()) {
case "int32":
return Integer.parseInt(stringData);
case "int8":
return Byte.parseByte(stringData);
case "int16":
return Short.parseShort(stringData);
case "int64":
return Long.parseLong(stringData);
default:
throw new IllegalArgumentException("Unknown format for integer " + ts.getFormat());
}
}
private Object convertString(final String stringData, final TypeSchema ts) {
if ("uint16".equals(ts.getFormat())) {
return stringData.charAt(0);
}
return stringData;
}
/**
* Create new instance of the specificied object from the supplied JSON String.
*
* @param format Details of the format needed
* @param jsonString JSON string
* @param ts TypeSchema
* @return new object
*/
@SuppressWarnings("PMD.AvoidAccessibilityAlteration")
Object createComponentInstance(final String format, final String jsonString, final TypeSchema ts) {
final DataTypeDefinition dtd = this.typeRegistry.getDataType(format);
Object obj;
try {
obj = dtd.getTypeClass().getDeclaredConstructor().newInstance();
} catch (IllegalAccessException
| InstantiationException
| InvocationTargetException
| NoSuchMethodException e1) {
throw new ContractRuntimeException("Unable to to create new instance of type", e1);
}
final JSONObject json = new JSONObject(jsonString);
// request validation of the type may throw an exception if validation fails
ts.validate(json);
try {
final Map fields = dtd.getProperties();
for (final PropertyDefinition prop : fields.values()) {
final Field f = prop.getField();
f.setAccessible(true);
final Object newValue = convert(json.get(prop.getName()).toString(), prop.getSchema());
f.set(obj, newValue);
}
return obj;
} catch (SecurityException
| IllegalArgumentException
| IllegalAccessException
| InstantiationException
| JSONException e) {
throw new ContractRuntimeException("Unable to convert JSON to object", e);
}
}
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/SerializerInterface.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.execution;
import org.hyperledger.fabric.contract.metadata.TypeSchema;
/**
* This interface allows contract developers to change the serialization mechanism. There are two scenarios where
* instances of DataTypes are serialized.
*
*
When the objects are (logically) transferred from the Client application to the Contract resulting in a
* transaction function being invoked. Typically this is JSON, hence a default JSON parser is provided.
*
*
The JSONTransactionSerializer can be extended if needed
*/
public interface SerializerInterface {
/**
* Convert the value supplied to a byte array, according to the TypeSchema.
*
* @param value
* @param ts
* @return buffer
*/
byte[] toBuffer(Object value, TypeSchema ts);
/**
* Take the byte buffer and return the object as required.
*
* @param buffer Byte buffer from the wire
* @param ts TypeSchema representing the type
* @return Object created; relies on Java auto-boxing for primitives
*/
Object fromBuffer(byte[] buffer, TypeSchema ts);
}
================================================
FILE: fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/execution/impl/ContractExecutionService.java
================================================
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.contract.execution.impl;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.ContractRuntimeException;
import org.hyperledger.fabric.contract.annotation.Serializer;
import org.hyperledger.fabric.contract.execution.ExecutionService;
import org.hyperledger.fabric.contract.execution.InvocationRequest;
import org.hyperledger.fabric.contract.execution.SerializerInterface;
import org.hyperledger.fabric.contract.metadata.TypeSchema;
import org.hyperledger.fabric.contract.routing.ParameterDefinition;
import org.hyperledger.fabric.contract.routing.TxFunction;
import org.hyperledger.fabric.contract.routing.impl.SerializerRegistryImpl;
import org.hyperledger.fabric.shim.Chaincode;
import org.hyperledger.fabric.shim.ChaincodeException;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.ResponseUtils;
public class ContractExecutionService implements ExecutionService {
private static final Logger LOGGER = Logger.getLogger(ContractExecutionService.class.getName());
private final SerializerRegistryImpl serializers;
/** @param serializers */
public ContractExecutionService(final SerializerRegistryImpl serializers) {
this.serializers = serializers;
}
/** */
@Override
public Chaincode.Response executeRequest(
final TxFunction txFn, final InvocationRequest req, final ChaincodeStub stub) {
LOGGER.fine(() -> "Routing Request" + txFn);
final TxFunction.Routing rd = txFn.getRouting();
Chaincode.Response response;
try {
final ContractInterface contractObject = rd.getContractInstance();
final Context context = contractObject.createContext(stub);
final List