From 4c42b34c9b4c225dc78a034c97c0a546713d079a Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Fri, 22 Apr 2022 15:19:06 -0700 Subject: [PATCH 01/10] initial pass of contract work --- buildSrc/src/main/kotlin/Dependencies.kt | 26 ++--- dc.sh | 50 ++++------ service/build.gradle.kts | 5 + service/docker/dependencies.yaml | 2 +- .../onboarding/domain/cee/ContractService.kt | 16 +++ .../ObjectStore.kt | 2 +- .../domain/provenance/Provenance.kt | 7 +- .../domain/usecase/cee/ExecuteContract.kt | 69 +++++++++++++ .../cee/model/ExecuteContractRequest.kt | 16 +++ .../domain/usecase/objectStore/GetAsset.kt | 16 ++- .../usecase/objectStore/SnapshotAsset.kt | 2 +- .../domain/usecase/objectStore/StoreAsset.kt | 2 +- .../specifications/WriteSpecifications.kt | 19 ---- .../model/WriteSpecificationsRequest.kt | 13 --- .../frameworks/cee/P8eContractService.kt | 76 ++++++++++++++ .../objectStore/ObjectStoreService.kt | 2 +- .../provenance/CachedAccountSequence.kt | 23 +++++ .../provenance/ProvenanceService.kt | 99 ++++++++++++------- .../provenance/exceptions/Exceptions.kt | 33 +++++++ .../extensions/ProvenanceExtensions.kt | 33 +++++++ .../provenance/utility/ProvenanceUtils.kt | 4 +- .../frameworks/web/external/cee/CeeApi.kt | 21 ++++ .../frameworks/web/external/cee/CeeHandler.kt | 17 ++++ .../web/external/provenance/ProvenanceApi.kt | 1 - .../external/provenance/ProvenanceHandler.kt | 8 +- 25 files changed, 436 insertions(+), 126 deletions(-) create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt rename service/src/main/kotlin/io/provenance/onboarding/domain/{provenance => objectStore}/ObjectStore.kt (94%) create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt delete mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/WriteSpecifications.kt delete mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/model/WriteSpecificationsRequest.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/CachedAccountSequence.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeApi.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeHandler.kt diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 390ae25e..68caaaf6 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -31,15 +31,15 @@ object Versions { const val KotlinFaker = "1.7.1" const val SpringMockk = "3.0.1" const val Swagger = "1.6.2" - const val AssetModel = "0.1.2" + const val AssetModel = "0.1.+" const val P8eScope = "0.4.9" - const val ProvenancePbc = Master - const val ProvenanceProtobuf = Master - const val WalletPbClient = Develop const val ProvenanceHdWallet = "0.1.15" - const val ProvenanceClient = "1.0.5" + const val ProvenanceClient = "1.1.1" const val Unirest = "3.13.6" const val KeyAccessLib = "0.2.+" + const val LoanPackage = "0.1.+" + const val Grpc = "1.45.0" + const val ProvenanceProto = "1.8.0" } object Plugins { // please keep this sorted in sections @@ -158,6 +158,7 @@ object Dependencies { val CoreKcache = DependencySpec("io.provenance:core-kcache", Versions.ProvenanceCore) val CoreKcacheSpring = DependencySpec("io.provenance:core-kcache-spring", Versions.ProvenanceCore) val CoreKafkaAggregator = DependencySpec("io.provenance:core-kafka-aggregator", Versions.ProvenanceCore) + val ProtoKotlin = DependencySpec("io.provenance:proto-kotlin", Versions.ProvenanceProto) val CoreKafkaAggregatorSpring = DependencySpec( "io.provenance:core-kafka-aggregator-spring", @@ -167,25 +168,24 @@ object Dependencies { "org.springframework.boot:spring-boot-starter-security" ) ) - val CoreLogging = DependencySpec("io.provenance:core-logging", Versions.ProvenanceCore) val AssetModel = DependencySpec("io.provenance.model:metadata-asset-model", Versions.AssetModel) + val LoanPackage = DependencySpec("io.provenance.loan-package:contract", Versions.LoanPackage) + object Client { val GrpcClientKotlin = DependencySpec("io.provenance.client:pb-grpc-client-kotlin", Versions.ProvenanceClient) } object HdWallet { val HdWallet = DependencySpec("io.provenance.hdwallet:hdwallet", Versions.ProvenanceHdWallet) - val HdWalletBase58 = DependencySpec("io.provenance.hdwallet:hdwallet-base58", Versions.ProvenanceHdWallet) - val HdWalletBech32 = DependencySpec("io.provenance.hdwallet:hdwallet-bech32", Versions.ProvenanceHdWallet) - val HdWalletBip32 = DependencySpec("io.provenance.hdwallet:hdwallet-bip32", Versions.ProvenanceHdWallet) val HdWalletBip39 = DependencySpec("io.provenance.hdwallet:hdwallet-bip39", Versions.ProvenanceHdWallet) - val HdWalletBip44 = DependencySpec("io.provenance.hdwallet:hdwallet-bip44", Versions.ProvenanceHdWallet) - val HdWalletEc = DependencySpec("io.provenance.hdwallet:hdwallet-ec", Versions.ProvenanceHdWallet) - val HdWalletSigner = DependencySpec("io.provenance.hdwallet:hdwallet-signer", Versions.ProvenanceHdWallet) - val HdWalletCommon = DependencySpec("io.provenance.hdwallet:hdwallet-common", Versions.ProvenanceHdWallet) } } + object Grpc { + val Protobuf = DependencySpec("io.grpc:grpc-protobuf", Versions.Grpc) + val Stub = DependencySpec("io.grpc:grpc-stub", Versions.Grpc) + } + val KotlinLogging = DependencySpec("io.github.microutils:kotlin-logging-jvm", Versions.KotlinLogging) val Ktlint = DependencySpec("com.pinterest:ktlint", Versions.Ktlint) diff --git a/dc.sh b/dc.sh index efdbae89..01818726 100755 --- a/dc.sh +++ b/dc.sh @@ -10,21 +10,21 @@ function up { sleep 2 sh service/docker/vault/init-and-unseal.sh 'http://127.0.0.1:8200' 'kv2_originations' sh service/docker/vault/add-secret.sh 'http://127.0.0.1:8200' 'kv2_originations' deadbeef-face-479b-860c-facefaceface \ - 0A4104F43FD6CD0DA184A666D444A4359EB9D38E06DB1EDC97B221DF90ED8189CFB8476EE2BF633DE0B4560F0D2BA284696C02ED31ADB32F09DEBE8D8906AA3E2BE71A \ - 0A410469BE2EC4699803FB7B49077F1CE0C88E2D2D41D23661EB1F420A72AA2B8DDF4325B349208B7F348C108B7C145FAEF41BB68FF338A75810522A89323E54BE91A6 \ - 0A4104DB326CF64C7466C2D63A2CD2C0401D1D6F8583C5F837C7510205DFB5CFA89D2115D0A3E0930D5FA01ACC664F1A182E1C0B43099D689B579849DEDDA1C63D0CF7 \ - 0A2009ABB890B396449706BB5998EEC6F6B0C795297B391A4BC2CF227B263555FF15 \ - 0A200B221F389D9B8E4964A8EB66F4EC07F83FCDD2E9DCE79B356FDDBE97767CF11C \ - 0A2100F5FE00731E3BC71F22CF054712A7C1F9A610848FC04BA81E6822D82D82C3562E \ + 0A41042C52EB79307D248B6CFB2A4AF562E403D4826BB0F540F024BBC3937528F6EB0B7FFA7A6585B751DBA25C173E658F3FEAAB0F05980C76E985CE0D55294F3600D7 \ + 0A41042C52EB79307D248B6CFB2A4AF562E403D4826BB0F540F024BBC3937528F6EB0B7FFA7A6585B751DBA25C173E658F3FEAAB0F05980C76E985CE0D55294F3600D7 \ + 0A41042C52EB79307D248B6CFB2A4AF562E403D4826BB0F540F024BBC3937528F6EB0B7FFA7A6585B751DBA25C173E658F3FEAAB0F05980C76E985CE0D55294F3600D7 \ + 0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4 \ + 0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4 \ + 0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4 \ "jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp" sh service/docker/vault/add-secret.sh 'http://127.0.0.1:8200' 'kv2_originations' deadbeef-face-2222-860c-facefaceface \ - 0A4104F43FD6CD0DA184A666D444A4359EB9D38E06DB1EDC97B221DF90ED8189CFB8476EE2BF633DE0B4560F0D2BA284696C02ED31ADB32F09DEBE8D8906AA3E2BE71A \ - 0A410469BE2EC4699803FB7B49077F1CE0C88E2D2D41D23661EB1F420A72AA2B8DDF4325B349208B7F348C108B7C145FAEF41BB68FF338A75810522A89323E54BE91A6 \ - 0A4104DB326CF64C7466C2D63A2CD2C0401D1D6F8583C5F837C7510205DFB5CFA89D2115D0A3E0930D5FA01ACC664F1A182E1C0B43099D689B579849DEDDA1C63D0CF7 \ - 0A2009ABB890B396449706BB5998EEC6F6B0C795297B391A4BC2CF227B263555FF15 \ - 0A200B221F389D9B8E4964A8EB66F4EC07F83FCDD2E9DCE79B356FDDBE97767CF11C \ - 0A2100F5FE00731E3BC71F22CF054712A7C1F9A610848FC04BA81E6822D82D82C3562E \ + 0A41042C52EB79307D248B6CFB2A4AF562E403D4826BB0F540F024BBC3937528F6EB0B7FFA7A6585B751DBA25C173E658F3FEAAB0F05980C76E985CE0D55294F3600D7 \ + 0A41042C52EB79307D248B6CFB2A4AF562E403D4826BB0F540F024BBC3937528F6EB0B7FFA7A6585B751DBA25C173E658F3FEAAB0F05980C76E985CE0D55294F3600D7 \ + 0A41042C52EB79307D248B6CFB2A4AF562E403D4826BB0F540F024BBC3937528F6EB0B7FFA7A6585B751DBA25C173E658F3FEAAB0F05980C76E985CE0D55294F3600D7 \ + 0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4 \ + 0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4 \ + 0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4 \ "jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp" docker ps -a @@ -39,23 +39,15 @@ function bounce { up } -function local_specs { - - ./cli/bin/cli write-specs-asset \ - --contract-spec-id "18573cf8-ddb9-491e-a4cb-bf2176160a63" \ - --scope-spec-id "997e8228-c37f-4668-9a66-6cfb3b2a23cd" \ - --key-mnemonic "jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp" \ - --chain-id local-chain \ - --node https://127.0.0.1:9090 \ - --raw-log - - ./cli/bin/cli write-specs-loan-state \ - --contract-spec-id "63a8bb4c-c6e0-4cb5-993b-b134c4b5cbbb" \ - --scope-spec-id "2eeada14-07cb-45fe-af6d-fdc48b627817" \ - --key-mnemonic "jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp" \ - --chain-id local-chain \ - --node https://127.0.0.1:9090 \ - --raw-log +function bootstrap { + echo "bootstrapping provenance contracts..." + export SIGNING_PRIVATE_KEY="0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4" + export ENCRYPTION_PRIVATE_KEY="0A2100AF41AAD44E6D0A1DF587491D01C11DB4E0F1BBDDE33F19CB2C4ADDDBE7FC82C4" + export OS_GRPC_URL="grpc://localhost:5001" + export PROVENANCE_GRPC_URL="grpc://localhost:9090" + export CHAIN_ID="chain-local" + cd "$CONTRACT_REPO" && ./gradlew --stop && ./gradlew p8eClean p8eBootstrap --info && ./gradlew publishToMavenLocal -xsignMavenPublication --info + #eventually publish to maven local } ${1} diff --git a/service/build.gradle.kts b/service/build.gradle.kts index 462dcef3..a07477ea 100644 --- a/service/build.gradle.kts +++ b/service/build.gradle.kts @@ -46,12 +46,17 @@ dependencies { Dependencies.Provenance.HdWallet.HdWallet, Dependencies.Provenance.HdWallet.HdWalletBip39, Dependencies.Provenance.Client.GrpcClientKotlin, + Dependencies.Provenance.ProtoKotlin, + Dependencies.Provenance.LoanPackage, Dependencies.Jackson.Databind, Dependencies.Jackson.Datatype, Dependencies.Jackson.Hubspot, Dependencies.Jackson.KotlinModule, Dependencies.Protobuf.JavaUtil, Dependencies.Kong.Unirest, + Dependencies.Grpc.Protobuf, + Dependencies.Grpc.Stub, + ).forEach { dep -> dep.implementation(this) } diff --git a/service/docker/dependencies.yaml b/service/docker/dependencies.yaml index d51ecc8a..d9bfa59c 100644 --- a/service/docker/dependencies.yaml +++ b/service/docker/dependencies.yaml @@ -2,7 +2,7 @@ version: '3.5' services: - postgres: + postgres-cee: image: postgres:13 container_name: postgres-cee environment: diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt new file mode 100644 index 00000000..02a9a1ed --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt @@ -0,0 +1,16 @@ +package io.provenance.onboarding.domain.cee + +import com.google.protobuf.Message +import cosmos.base.abci.v1beta1.Abci +import io.provenance.client.grpc.Signer +import io.provenance.onboarding.frameworks.provenance.SingleTx +import io.provenance.scope.contract.spec.P8eContract +import io.provenance.scope.sdk.Client +import io.provenance.scope.sdk.Session +import java.util.UUID + +interface ContractService { + fun getContract(contractName: String, basePackage: String = "io.provenance.scope.loan.contracts"): Class + fun setupContract(client: Client, contractClass: Class, records: Map, scopeUuid: UUID, sessionUuid: UUID? = null): Session + fun executeContract(client: Client, signer: Signer, contractClass: Class, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse) +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/ObjectStore.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/objectStore/ObjectStore.kt similarity index 94% rename from service/src/main/kotlin/io/provenance/onboarding/domain/provenance/ObjectStore.kt rename to service/src/main/kotlin/io/provenance/onboarding/domain/objectStore/ObjectStore.kt index f443bd19..eaedb7cf 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/ObjectStore.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/objectStore/ObjectStore.kt @@ -1,4 +1,4 @@ -package io.provenance.onboarding.domain.provenance +package io.provenance.onboarding.domain.objectStore import io.provenance.onboarding.domain.usecase.objectStore.model.StoreAssetResponse import io.provenance.scope.encryption.proto.Encryption diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt index cd864d26..4a0ec284 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt @@ -1,11 +1,14 @@ package io.provenance.onboarding.domain.provenance +import cosmos.base.abci.v1beta1.Abci +import io.provenance.client.grpc.Signer import io.provenance.hdwallet.wallet.Account import io.provenance.onboarding.domain.usecase.common.model.TxBody import io.provenance.onboarding.domain.usecase.provenance.tx.model.OnboardAssetResponse -import java.util.UUID +import io.provenance.onboarding.frameworks.provenance.ProvenanceTx +import io.provenance.scope.sdk.Session interface Provenance { fun onboard(chainId: String, nodeEndpoint: String, account: Account, storeTxBody: TxBody): OnboardAssetResponse - fun writeSpecifications(chainId: String, nodeEndpoint: String, account: Account, scopeId: UUID, contractSpecId: UUID, scopeSpecId: UUID, type: String) + fun executeTransaction(chainId: String, nodeEndpoint: String, session: Session, tx: ProvenanceTx, signer: Signer): Abci.TxResponse } diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt new file mode 100644 index 00000000..2241d47c --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt @@ -0,0 +1,69 @@ +package io.provenance.onboarding.domain.usecase.cee + +import io.provenance.core.KeyType +import io.provenance.onboarding.domain.cee.ContractService +import io.provenance.onboarding.domain.provenance.Provenance +import io.provenance.onboarding.domain.usecase.AbstractUseCase +import io.provenance.onboarding.domain.usecase.cee.model.ExecuteContractRequest +import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator +import io.provenance.onboarding.domain.usecase.provenance.account.GetAccount +import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils +import io.provenance.scope.contract.proto.Specifications +import io.provenance.scope.encryption.model.DirectKeyRef +import io.provenance.scope.encryption.util.toJavaPrivateKey +import io.provenance.scope.encryption.util.toJavaPublicKey +import io.provenance.scope.sdk.Affiliate +import io.provenance.scope.sdk.Client +import io.provenance.scope.sdk.ClientConfig +import io.provenance.scope.sdk.SharedClient +import java.net.URI +import java.security.KeyPair +import java.util.concurrent.TimeUnit +import org.springframework.stereotype.Component + +@Component +class ExecuteContract( + private val getOriginator: GetOriginator, + private val contractService: ContractService, + private val provenanceService: Provenance, + private val getAccount: GetAccount +) : AbstractUseCase() { + override suspend fun execute(args: ExecuteContractRequest) { + val utils = ProvenanceUtils() + val sharedClient = SharedClient( + ClientConfig( + mainNet = !args.isTestNet, + cacheJarSizeInBytes = 4L * 1024 * 1024, // ~ 4 MB, + cacheRecordSizeInBytes = 0L, + cacheSpecSizeInBytes = 0L, + disableContractLogs = !args.isTestNet, + osConcurrencySize = 6, + osGrpcUrl = URI(args.objectStoreUrl), + osChannelCustomizeFn = { channelBuilder -> + channelBuilder + .idleTimeout(1, TimeUnit.MINUTES) + .keepAliveTime(10, TimeUnit.SECONDS) + .keepAliveTimeout(10, TimeUnit.SECONDS) + } + ) + ) + + val originator = getOriginator.execute(args.account.originatorUuid) + val affiliate = Affiliate( + signingKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), + encryptionKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), + Specifications.PartyType.valueOf(args.partyType), + ) + + val client = Client(sharedClient, affiliate) + val account = getAccount.execute(args.account) + + val contract = contractService.getContract(args.contractName) + val session = contractService.setupContract(client, contract, emptyMap(), args.scopeUuid, args.sessionUuid) + val signer = utils.getSigner(account) + + contractService.executeContract(client, signer, contract, session) { tx -> + provenanceService.executeTransaction(args.chainId, args.nodeEndpoint, session, tx, signer) + } + } +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt new file mode 100644 index 00000000..50c39161 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt @@ -0,0 +1,16 @@ +package io.provenance.onboarding.domain.usecase.cee.model + +import io.provenance.onboarding.domain.usecase.common.model.AccountInfo +import java.util.UUID + +data class ExecuteContractRequest( + val contractName: String, + val scopeUuid: UUID, + val sessionUuid: UUID, + val objectStoreUrl: String, + val partyType: String, + val isTestNet: Boolean, + val account: AccountInfo, + val chainId: String, + val nodeEndpoint: String +) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt index ef06a7aa..d624a65e 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt @@ -1,19 +1,28 @@ package io.provenance.onboarding.domain.usecase.objectStore import io.provenance.core.KeyType -import io.provenance.onboarding.domain.provenance.ObjectStore +import io.provenance.hdwallet.ec.extensions.toJavaECPrivateKey +import io.provenance.hdwallet.ec.extensions.toJavaECPublicKey +import io.provenance.onboarding.domain.objectStore.ObjectStore +import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.objectStore.model.GetAssetRequest import io.provenance.onboarding.frameworks.config.ObjectStoreConfig +import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils +import io.provenance.scope.encryption.util.toHex import io.provenance.scope.encryption.util.toJavaPrivateKey import io.provenance.scope.encryption.util.toJavaPublicKey import io.provenance.scope.objectstore.client.OsClient import io.provenance.scope.objectstore.util.base64Decode +import io.provenance.scope.objectstore.util.toHex import org.springframework.stereotype.Component import tech.figure.asset.v1beta1.Asset import java.lang.IllegalStateException import java.net.URI +import mu.KotlinLogging + +private val log = KotlinLogging.logger { } @Component class GetAsset( @@ -22,6 +31,11 @@ class GetAsset( private val objectStoreConfig: ObjectStoreConfig, ) : AbstractUseCase() { override suspend fun execute(args: GetAssetRequest): String { + + val utils = ProvenanceUtils() + val account = utils.getAccount("jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp", true, 0, 0) + log.info(account.keyPair.publicKey.toJavaECPublicKey().toHex()) + val originator = getOriginator.execute(args.originatorUuid) val osClient = OsClient(URI.create(args.objectStoreAddress), objectStoreConfig.timeoutMs) val publicKey = (originator.keys[KeyType.ENCRYPTION_PUBLIC_KEY] as? String)?.toJavaPublicKey() diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/SnapshotAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/SnapshotAsset.kt index 112862c5..c782faeb 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/SnapshotAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/SnapshotAsset.kt @@ -1,7 +1,7 @@ package io.provenance.onboarding.domain.usecase.objectStore import io.provenance.core.KeyType -import io.provenance.onboarding.domain.provenance.ObjectStore +import io.provenance.onboarding.domain.objectStore.ObjectStore import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.objectStore.model.SnapshotAssetRequest diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/StoreAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/StoreAsset.kt index f78839f1..6757d5be 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/StoreAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/StoreAsset.kt @@ -1,7 +1,7 @@ package io.provenance.onboarding.domain.usecase.objectStore import io.provenance.core.KeyType -import io.provenance.onboarding.domain.provenance.ObjectStore +import io.provenance.onboarding.domain.objectStore.ObjectStore import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.objectStore.model.StoreAssetRequest diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/WriteSpecifications.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/WriteSpecifications.kt deleted file mode 100644 index 4056f040..00000000 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/WriteSpecifications.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.provenance.onboarding.domain.usecase.provenance.specifications - -import io.provenance.onboarding.domain.provenance.Provenance -import io.provenance.onboarding.domain.usecase.AbstractUseCase -import io.provenance.onboarding.domain.usecase.provenance.account.GetAccount -import io.provenance.onboarding.domain.usecase.provenance.specifications.model.WriteSpecificationsRequest -import org.springframework.stereotype.Component - -@Component -class WriteSpecifications( - private val provenance: Provenance, - private val getAccount: GetAccount -) : AbstractUseCase() { - override suspend fun execute(args: WriteSpecificationsRequest) { - - val account = getAccount.execute(args.account) - provenance.writeSpecifications(args.chainId, args.nodeEndpoint, account, args.scopeId, args.contractSpecId, args.scopeSpecId, "asset") - } -} diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/model/WriteSpecificationsRequest.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/model/WriteSpecificationsRequest.kt deleted file mode 100644 index c18b4c50..00000000 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/specifications/model/WriteSpecificationsRequest.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.provenance.onboarding.domain.usecase.provenance.specifications.model - -import io.provenance.onboarding.domain.usecase.common.model.AccountInfo -import java.util.UUID - -data class WriteSpecificationsRequest( - val chainId: String, - val nodeEndpoint: String, - val account: AccountInfo, - val scopeId: UUID, - val contractSpecId: UUID, - val scopeSpecId: UUID, -) diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt new file mode 100644 index 00000000..01e46b98 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt @@ -0,0 +1,76 @@ +package io.provenance.onboarding.frameworks.cee + +import com.google.protobuf.Message +import cosmos.base.abci.v1beta1.Abci +import io.provenance.client.grpc.Signer +import io.provenance.onboarding.domain.cee.ContractService +import io.provenance.onboarding.frameworks.provenance.SingleTx +import io.provenance.scope.contract.spec.P8eContract +import io.provenance.scope.loan.LoanScopeSpecification +import io.provenance.scope.loan.contracts.AppendLoanDocContract +import io.provenance.scope.loan.utility.LoanPackageContract +import io.provenance.scope.sdk.Client +import io.provenance.scope.sdk.Session +import io.provenance.scope.sdk.SignedResult +import java.util.UUID +import kotlin.reflect.cast +import kotlin.reflect.full.createInstance +import mu.KotlinLogging +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider +import org.springframework.core.type.filter.AnnotationTypeFilter +import org.springframework.stereotype.Component + +@Component +class P8eContractService : ContractService { + private val log = KotlinLogging.logger { } + + override fun getContract(contractName: String, basePackage: String): Class { + val provider = ClassPathScanningCandidateComponentProvider(false) + provider.addIncludeFilter(AnnotationTypeFilter(LoanPackageContract::class.java)) + val candidates = provider.findCandidateComponents(basePackage) + val contractType = candidates.map { Class.forName(it.beanClassName) }.singleOrNull { it.getAnnotation(LoanPackageContract::class.java)?.type == contractName } + ?: throw IllegalStateException("NO~!") + +// val a = contractType.kotlin.createInstance() as P8eContract +// return a.javaClass + val a = contractType.asSubclass(P8eContract::class.java) + + + return a + } + + override fun setupContract( + client: Client, + contractClass: Class, + records: Map, + scopeUuid: UUID, + sessionUuid: UUID? + ): Session = + client + .newSession(contractClass, LoanScopeSpecification::class.java) + .setScopeUuid(scopeUuid) + .configureSession(records, sessionUuid) + .also { session -> + log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contractClass.simpleName} has been setup.") + } + + override fun executeContract(client: Client, signer: Signer, contractClass: Class, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse) = + runCatching { + when (val result = client.execute(session)) { + is SignedResult -> executeTransaction(SingleTx(result)) + else -> throw IllegalStateException("Must be a signed result since this is a single party contract.") + } + }.fold( + onSuccess = { result -> + log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contractClass.simpleName} is pending. The tx hash is ${result.txhash}.") + }, + onFailure = { throwable -> + log.error("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contractClass.simpleName} has failed execution. An error occurred.", throwable) + } + ) + + private fun Session.Builder.configureSession(records: Map, sessionUuid: UUID? = null): Session = + this.setSessionUuid(sessionUuid ?: UUID.randomUUID()) + .also { records.forEach { record -> it.addProposedRecord(record.key, record.value) } } + .build() +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/objectStore/ObjectStoreService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/objectStore/ObjectStoreService.kt index bc4523a2..ef4db3a5 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/objectStore/ObjectStoreService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/objectStore/ObjectStoreService.kt @@ -2,7 +2,7 @@ package io.provenance.onboarding.frameworks.objectStore import com.google.protobuf.Message import io.provenance.objectstore.proto.Objects -import io.provenance.onboarding.domain.provenance.ObjectStore +import io.provenance.onboarding.domain.objectStore.ObjectStore import io.provenance.onboarding.domain.usecase.objectStore.model.StoreAssetResponse import io.provenance.onboarding.domain.usecase.objectStore.model.toModel import io.provenance.onboarding.frameworks.config.ObjectStoreConfig diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/CachedAccountSequence.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/CachedAccountSequence.kt new file mode 100644 index 00000000..724f2784 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/CachedAccountSequence.kt @@ -0,0 +1,23 @@ +package io.provenance.onboarding.frameworks.provenance + +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicLong + +class CachedAccountSequence { + private val lastKnownSequence = AtomicLong(0L) + private val offset = AtomicInteger(0) + + fun getAndIncrementOffset(currentSequence: Long): Int { + if (lastKnownSequence.get() != currentSequence || offset.get() > 5) { + lastKnownSequence.set(currentSequence) + offset.set(0) + } + return offset.getAndIncrement() + } + + fun getAndDecrement(usedSequence: Long) { + if (lastKnownSequence.get() == usedSequence && offset.get() != 0) { + offset.getAndDecrement() + } + } +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt index 67d48eb9..50c1d8c9 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt @@ -2,26 +2,88 @@ package io.provenance.onboarding.frameworks.provenance import com.google.common.io.BaseEncoding import com.google.protobuf.Any +import cosmos.base.abci.v1beta1.Abci import cosmos.tx.v1beta1.ServiceOuterClass import cosmos.tx.v1beta1.TxOuterClass import io.provenance.client.grpc.BaseReqSigner import io.provenance.client.grpc.GasEstimationMethod import io.provenance.client.grpc.PbClient +import io.provenance.client.grpc.Signer import io.provenance.hdwallet.wallet.Account import io.provenance.onboarding.domain.provenance.Provenance -import io.provenance.onboarding.domain.usecase.common.model.ScopeConfig import io.provenance.onboarding.domain.usecase.common.model.TxBody import io.provenance.onboarding.domain.usecase.provenance.tx.model.OnboardAssetResponse +import io.provenance.onboarding.frameworks.provenance.exceptions.ContractExceptionException +import io.provenance.onboarding.frameworks.provenance.extensions.getBaseAccount +import io.provenance.onboarding.frameworks.provenance.extensions.getCurrentHeight +import io.provenance.onboarding.frameworks.provenance.extensions.getErrorResult +import io.provenance.onboarding.frameworks.provenance.extensions.isError import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils +import io.provenance.scope.sdk.Session +import io.provenance.scope.sdk.SignedResult import org.springframework.stereotype.Component import java.net.URI -import java.util.UUID +import java.util.concurrent.ConcurrentHashMap +import mu.KotlinLogging + +class ProvenanceTxException(message: String) : Exception(message) + +sealed class ProvenanceTx +class SingleTx(val value: SignedResult) : ProvenanceTx() +class BatchTx(val value: Collection) : ProvenanceTx() @Component class ProvenanceService : Provenance { + private val log = KotlinLogging.logger { } + private val cachedSequenceMap = ConcurrentHashMap() + + override fun executeTransaction(chainId: String, nodeEndpoint: String, session: Session, tx: ProvenanceTx, signer: Signer): Abci.TxResponse { + val pbClient = PbClient(chainId, URI(nodeEndpoint), GasEstimationMethod.MSG_FEE_CALCULATION) + + return when (tx) { + is SingleTx -> { + when (val error = tx.getErrorResult()) { + null -> { + log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] Building the tx.") + val messages = tx.value.messages.map { Any.pack(it, "") } + val txBody = TxOuterClass.TxBody.newBuilder() + .setTimeoutHeight(pbClient.tendermintService.getCurrentHeight() + 12L) + .addAllMessages(messages) + .build() + + log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] Determining account information for the tx.") + val cachedOffset = cachedSequenceMap.getOrPut(signer.address()) { CachedAccountSequence() } + val account = pbClient.authClient.getBaseAccount(signer.address()) + val baseSigner = BaseReqSigner( + signer, + account = account, + sequenceOffset = cachedOffset.getAndIncrementOffset(account.sequence) + ) + + log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] Sending tx.") + val result = pbClient.estimateAndBroadcastTx( + txBody = txBody, + signers = listOf(baseSigner), + gasAdjustment = 1.5, + mode = ServiceOuterClass.BroadcastMode.BROADCAST_MODE_BLOCK + ) + + if (result.isError()) { + cachedOffset.getAndDecrement(account.sequence) + throw ProvenanceTxException(result.txResponse.toString()) + } + result.txResponse + } + else -> throw ContractExceptionException(error.result.errorMessage) + } + } + is BatchTx -> throw IllegalArgumentException("Batched transactions are not supported.") + } + } + override fun onboard(chainId: String, nodeEndpoint: String, account: Account, storeTxBody: TxBody): OnboardAssetResponse { - val pbClient = setupProvenanceClient(chainId, nodeEndpoint) + val pbClient = PbClient(chainId, URI(nodeEndpoint), GasEstimationMethod.MSG_FEE_CALCULATION) val utility = ProvenanceUtils() val txBody = TxOuterClass.TxBody.newBuilder().also { @@ -39,35 +101,4 @@ class ProvenanceService : Provenance { return OnboardAssetResponse(response.txhash, response.gasWanted.toString(), response.gasUsed.toString(), response.height.toString()) } - - override fun writeSpecifications(chainId: String, nodeEndpoint: String, account: Account, scopeId: UUID, contractSpecId: UUID, scopeSpecId: UUID, type: String) { - val pbClient = setupProvenanceClient(chainId, nodeEndpoint) - val utility = ProvenanceUtils() - - val txBody = if (type == "asset") { - utility.buildAssetSpecificationMetadataTransaction( - ScopeConfig( - scopeId = scopeId, - contractSpecId = contractSpecId, - scopeSpecId = scopeSpecId - ), - account.address.value - ) - } else { - throw IllegalArgumentException("write-specs is misconfigured for type $type") - } - - pbClient.estimateAndBroadcastTx( - txBody = txBody, - signers = listOf(BaseReqSigner(utility.getSigner(account))), - mode = ServiceOuterClass.BroadcastMode.BROADCAST_MODE_SYNC, - gasAdjustment = 1.5 - ).also { - it.txResponse.apply { - println("TX (height: $height, txhash: $txhash, code: $code, gasWanted: $gasWanted, gasUsed: $gasUsed)") - } - } - } - - private fun setupProvenanceClient(chainId: String, nodeEndpoint: String) = PbClient(chainId, URI(nodeEndpoint), GasEstimationMethod.MSG_FEE_CALCULATION) } diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt new file mode 100644 index 00000000..eacb5534 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt @@ -0,0 +1,33 @@ +package io.provenance.onboarding.frameworks.provenance.exceptions + +import java.util.UUID + +open class CannotOnboardUnfundedLoanException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class ContractExceptionException(message: String? = "", val shouldRetry: Boolean = false, cause: Throwable? = null) : RuntimeException(message, cause) + +open class ContractInProgressException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class ContractRetryException(message: String? = "", val willRetry: Boolean = true, cause: Throwable? = null) : RuntimeException(message, cause) + +open class InsufficientFundsException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class InvalidFactException(message: String? = "", val factName: String? = null, cause: Throwable? = null) : RuntimeException(message, cause) + +open class InvalidLoanFactException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class InvalidLoanTypeException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class InvalidOriginatorException(message: String? = "", val originatorUuid: UUID? = null, cause: Throwable? = null) : RuntimeException(message, cause) + +open class NotificationException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class ResourceNotFoundException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class LoanAlreadyExistsException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class LoanFundingPaused(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class WontRunLoanValidationException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class ExistingScopeNotChangedException(message: String) : java.lang.RuntimeException(message) diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt new file mode 100644 index 00000000..7ba4b3b1 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt @@ -0,0 +1,33 @@ +package io.provenance.onboarding.frameworks.provenance.extensions + +import cosmos.auth.v1beta1.Auth +import cosmos.base.abci.v1beta1.Abci.TxResponse +import cosmos.base.tendermint.v1beta1.Query +import cosmos.tx.v1beta1.ServiceOuterClass.BroadcastTxResponse +import io.provenance.onboarding.frameworks.provenance.SingleTx +import io.provenance.scope.contract.proto.Contracts +import java.util.concurrent.TimeUnit + +fun BroadcastTxResponse.isError() = txResponse.isError() + +fun TxResponse.isError() = code > 0 + +fun TxResponse.isSuccess() = !isError() && height > 0 + +fun TxResponse.getError(): String = + logsList.filter { it.log.isNotBlank() }.takeIf { it.isNotEmpty() }?.joinToString("; ") { it.log } ?: rawLog + +fun SingleTx.getErrorResult() = + this.value.envelopeState.result.contract.considerationsList.firstOrNull { it.result.result == Contracts.ExecutionResult.Result.FAIL } + +fun cosmos.tx.v1beta1.ServiceGrpc.ServiceBlockingStub.getTx(hash: String) = this.withDeadlineAfter(10, TimeUnit.SECONDS) + .getTx(cosmos.tx.v1beta1.ServiceOuterClass.GetTxRequest.newBuilder().setHash(hash).build()) + .txResponse + +fun cosmos.base.tendermint.v1beta1.ServiceGrpc.ServiceBlockingStub.getCurrentHeight(): Long = this + .withDeadlineAfter(10, TimeUnit.SECONDS) + .getLatestBlock(Query.GetLatestBlockRequest.getDefaultInstance()).block.header.height + +fun cosmos.auth.v1beta1.QueryGrpc.QueryBlockingStub.getBaseAccount(address: String): Auth.BaseAccount = this + .withDeadlineAfter(10, TimeUnit.SECONDS) + .getBaseAccount(address) diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/utility/ProvenanceUtils.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/utility/ProvenanceUtils.kt index 8261ed5e..b736ca78 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/utility/ProvenanceUtils.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/utility/ProvenanceUtils.kt @@ -6,8 +6,8 @@ import com.google.protobuf.ByteString import cosmos.crypto.secp256k1.Keys import cosmos.tx.v1beta1.TxOuterClass import io.provenance.client.grpc.Signer -import io.provenance.client.wallet.NetworkType import io.provenance.hdwallet.bip39.MnemonicWords +import io.provenance.hdwallet.hrp.Hrp import io.provenance.hdwallet.wallet.Account import io.provenance.hdwallet.wallet.Wallet import io.provenance.metadata.v1.DefinitionType @@ -262,7 +262,7 @@ class ProvenanceUtils { fun getAccount(keyMnemonic: String, isTestNet: Boolean, keyRingIndex: Int, keyIndex: Int) = Wallet.fromMnemonic( - hrp = NetworkType.TESTNET.prefix, + hrp = Hrp.ProvenanceBlockchain.testnet, passphrase = "", mnemonicWords = MnemonicWords.of(keyMnemonic), testnet = isTestNet diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeApi.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeApi.kt new file mode 100644 index 00000000..9ea12e6b --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeApi.kt @@ -0,0 +1,21 @@ +package io.provenance.onboarding.frameworks.web.external.cee + +import io.provenance.onboarding.frameworks.web.Routes +import io.provenance.onboarding.frameworks.web.logging.logExchange +import mu.KotlinLogging +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.reactive.function.server.coRouter + +private val log = KotlinLogging.logger {} + +@Configuration +class CeeApi { + @Bean + fun externalCeeApiV1(handler: CeeHandler) = coRouter { + logExchange(log) + "${Routes.EXTERNAL_BASE_V1}/cee".nest { + POST("/execute", handler::executeContract) + } + } +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeHandler.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeHandler.kt new file mode 100644 index 00000000..75b8948a --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/cee/CeeHandler.kt @@ -0,0 +1,17 @@ +package io.provenance.onboarding.frameworks.web.external.cee + +import io.provenance.onboarding.domain.usecase.cee.ExecuteContract +import io.provenance.onboarding.frameworks.web.misc.foldToServerResponse +import org.springframework.stereotype.Component +import org.springframework.web.reactive.function.server.ServerRequest +import org.springframework.web.reactive.function.server.ServerResponse +import org.springframework.web.reactive.function.server.awaitBody + +@Component +class CeeHandler( + private val executeContract: ExecuteContract, +) { + suspend fun executeContract(req: ServerRequest): ServerResponse = runCatching { + executeContract.execute(req.awaitBody()) + }.foldToServerResponse() +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceApi.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceApi.kt index 20c79c40..6d1de737 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceApi.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceApi.kt @@ -16,7 +16,6 @@ class ProvenanceApi { logExchange(log) "${Routes.EXTERNAL_BASE_V1}/p8e".nest { POST("/onboard", handler::createTxAndOnboard) - POST("/specifications", handler::writeSpecifications) POST("/tx/generate", handler::generateTx) POST("/tx/execute", handler::executeTx) } diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceHandler.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceHandler.kt index 05f5e951..fa5517dd 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceHandler.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/web/external/provenance/ProvenanceHandler.kt @@ -1,6 +1,5 @@ package io.provenance.onboarding.frameworks.web.external.provenance -import io.provenance.onboarding.domain.usecase.provenance.specifications.WriteSpecifications import io.provenance.onboarding.domain.usecase.provenance.tx.CreateTx import io.provenance.onboarding.domain.usecase.provenance.tx.CreateTxOnboardAsset import io.provenance.onboarding.domain.usecase.provenance.tx.ExecuteTx @@ -14,8 +13,7 @@ import org.springframework.web.reactive.function.server.awaitBody class ProvenanceHandler( private val executeTx: ExecuteTx, private val createTx: CreateTx, - private val createTxAndOnboardAsset: CreateTxOnboardAsset, - private val writeSpecifications: WriteSpecifications, + private val createTxAndOnboardAsset: CreateTxOnboardAsset ) { suspend fun createTxAndOnboard(req: ServerRequest): ServerResponse = runCatching { createTxAndOnboardAsset.execute(req.awaitBody()) @@ -28,8 +26,4 @@ class ProvenanceHandler( suspend fun executeTx(req: ServerRequest): ServerResponse = runCatching { executeTx.execute(req.awaitBody()) }.foldToServerResponse() - - suspend fun writeSpecifications(req: ServerRequest): ServerResponse = runCatching { - writeSpecifications.execute(req.awaitBody()) - }.foldToServerResponse() } From 424ea679fd783cfaeb6b7e6bc3bbc9481661f166 Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Sun, 24 Apr 2022 16:24:56 -0700 Subject: [PATCH 02/10] cleanup --- .../onboarding/domain/usecase/objectStore/GetAsset.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt index d624a65e..559836ab 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt @@ -31,11 +31,6 @@ class GetAsset( private val objectStoreConfig: ObjectStoreConfig, ) : AbstractUseCase() { override suspend fun execute(args: GetAssetRequest): String { - - val utils = ProvenanceUtils() - val account = utils.getAccount("jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp", true, 0, 0) - log.info(account.keyPair.publicKey.toJavaECPublicKey().toHex()) - val originator = getOriginator.execute(args.originatorUuid) val osClient = OsClient(URI.create(args.objectStoreAddress), objectStoreConfig.timeoutMs) val publicKey = (originator.keys[KeyType.ENCRYPTION_PUBLIC_KEY] as? String)?.toJavaPublicKey() From 07d14f31508813023043d8e429688f6a29a97333 Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Sun, 24 Apr 2022 16:24:56 -0700 Subject: [PATCH 03/10] cleanup --- dc.sh | 19 ------------------- .../domain/usecase/objectStore/GetAsset.kt | 5 ----- .../frameworks/cee/P8eContractService.kt | 9 ++------- 3 files changed, 2 insertions(+), 31 deletions(-) diff --git a/dc.sh b/dc.sh index baa9d0d3..ba61e75a 100755 --- a/dc.sh +++ b/dc.sh @@ -39,23 +39,4 @@ function bounce { up } -function local_specs { - - ./cli/bin/cli write-specs-asset \ - --contract-spec-id "18573cf8-ddb9-491e-a4cb-bf2176160a63" \ - --scope-spec-id "997e8228-c37f-4668-9a66-6cfb3b2a23cd" \ - --key-mnemonic "jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp" \ - --chain-id local-chain \ - --node https://127.0.0.1:9090 \ - --raw-log - - ./cli/bin/cli write-specs-loan-state \ - --contract-spec-id "63a8bb4c-c6e0-4cb5-993b-b134c4b5cbbb" \ - --scope-spec-id "2eeada14-07cb-45fe-af6d-fdc48b627817" \ - --key-mnemonic "jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp" \ - --chain-id local-chain \ - --node https://127.0.0.1:9090 \ - --raw-log -} - ${1} diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt index d624a65e..559836ab 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt @@ -31,11 +31,6 @@ class GetAsset( private val objectStoreConfig: ObjectStoreConfig, ) : AbstractUseCase() { override suspend fun execute(args: GetAssetRequest): String { - - val utils = ProvenanceUtils() - val account = utils.getAccount("jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp", true, 0, 0) - log.info(account.keyPair.publicKey.toJavaECPublicKey().toHex()) - val originator = getOriginator.execute(args.originatorUuid) val osClient = OsClient(URI.create(args.objectStoreAddress), objectStoreConfig.timeoutMs) val publicKey = (originator.keys[KeyType.ENCRYPTION_PUBLIC_KEY] as? String)?.toJavaPublicKey() diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt index 01e46b98..24e51259 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt @@ -29,14 +29,9 @@ class P8eContractService : ContractService { provider.addIncludeFilter(AnnotationTypeFilter(LoanPackageContract::class.java)) val candidates = provider.findCandidateComponents(basePackage) val contractType = candidates.map { Class.forName(it.beanClassName) }.singleOrNull { it.getAnnotation(LoanPackageContract::class.java)?.type == contractName } - ?: throw IllegalStateException("NO~!") + ?: throw IllegalStateException("Failed to find contract.") -// val a = contractType.kotlin.createInstance() as P8eContract -// return a.javaClass - val a = contractType.asSubclass(P8eContract::class.java) - - - return a + return contractType.asSubclass(P8eContract::class.java) } override fun setupContract( From bf46427bd329369501324bda6bc18bf9dc59504f Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Mon, 25 Apr 2022 12:11:21 -0700 Subject: [PATCH 04/10] removing dependency on loan package repo --- build.gradle.kts | 3 ++- dc.sh | 2 +- .../onboarding/domain/cee/ContractService.kt | 2 +- .../domain/usecase/objectStore/GetAsset.kt | 9 --------- .../frameworks/cee/P8eContractService.kt | 15 ++++----------- 5 files changed, 8 insertions(+), 23 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a5b97420..a8e96e3b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import net.swiftzer.semver.SemVer buildscript { @@ -24,6 +23,7 @@ subprojects { } repositories { + mavenLocal() mavenCentral() } @@ -107,6 +107,7 @@ allprojects { version = semVersion repositories { + mavenLocal() mavenCentral() } } diff --git a/dc.sh b/dc.sh index b621f441..6296f1a6 100755 --- a/dc.sh +++ b/dc.sh @@ -54,7 +54,7 @@ function publish() { if [[ -d "$FULL_PATH" ]]; then pushd $PATH_TO_CONTRACTS > /dev/null - ./gradlew p8eClean p8eBootstrap --info + ./gradlew p8eClean p8eCheck p8eBootstrap publishToMavenLocal -xsignMavenPublication --info popd > /dev/null else echo "Invalid path. Provide a valid path to the contracts directory you wish to publish." diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt index 02a9a1ed..1239399e 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt @@ -10,7 +10,7 @@ import io.provenance.scope.sdk.Session import java.util.UUID interface ContractService { - fun getContract(contractName: String, basePackage: String = "io.provenance.scope.loan.contracts"): Class + fun getContract(contractName: String): Class fun setupContract(client: Client, contractClass: Class, records: Map, scopeUuid: UUID, sessionUuid: UUID? = null): Session fun executeContract(client: Client, signer: Signer, contractClass: Class, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse) } diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt index 559836ab..6d78d524 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt @@ -1,28 +1,19 @@ package io.provenance.onboarding.domain.usecase.objectStore import io.provenance.core.KeyType -import io.provenance.hdwallet.ec.extensions.toJavaECPrivateKey -import io.provenance.hdwallet.ec.extensions.toJavaECPublicKey import io.provenance.onboarding.domain.objectStore.ObjectStore -import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.objectStore.model.GetAssetRequest import io.provenance.onboarding.frameworks.config.ObjectStoreConfig -import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils -import io.provenance.scope.encryption.util.toHex import io.provenance.scope.encryption.util.toJavaPrivateKey import io.provenance.scope.encryption.util.toJavaPublicKey import io.provenance.scope.objectstore.client.OsClient import io.provenance.scope.objectstore.util.base64Decode -import io.provenance.scope.objectstore.util.toHex import org.springframework.stereotype.Component import tech.figure.asset.v1beta1.Asset import java.lang.IllegalStateException import java.net.URI -import mu.KotlinLogging - -private val log = KotlinLogging.logger { } @Component class GetAsset( diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt index 24e51259..c54a01d6 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt @@ -5,16 +5,15 @@ import cosmos.base.abci.v1beta1.Abci import io.provenance.client.grpc.Signer import io.provenance.onboarding.domain.cee.ContractService import io.provenance.onboarding.frameworks.provenance.SingleTx +import io.provenance.scope.contract.contracts.ContractHash import io.provenance.scope.contract.spec.P8eContract import io.provenance.scope.loan.LoanScopeSpecification -import io.provenance.scope.loan.contracts.AppendLoanDocContract import io.provenance.scope.loan.utility.LoanPackageContract import io.provenance.scope.sdk.Client import io.provenance.scope.sdk.Session import io.provenance.scope.sdk.SignedResult +import java.util.ServiceLoader import java.util.UUID -import kotlin.reflect.cast -import kotlin.reflect.full.createInstance import mu.KotlinLogging import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider import org.springframework.core.type.filter.AnnotationTypeFilter @@ -24,14 +23,8 @@ import org.springframework.stereotype.Component class P8eContractService : ContractService { private val log = KotlinLogging.logger { } - override fun getContract(contractName: String, basePackage: String): Class { - val provider = ClassPathScanningCandidateComponentProvider(false) - provider.addIncludeFilter(AnnotationTypeFilter(LoanPackageContract::class.java)) - val candidates = provider.findCandidateComponents(basePackage) - val contractType = candidates.map { Class.forName(it.beanClassName) }.singleOrNull { it.getAnnotation(LoanPackageContract::class.java)?.type == contractName } - ?: throw IllegalStateException("Failed to find contract.") - - return contractType.asSubclass(P8eContract::class.java) + override fun getContract(contractName: String): Class { + return Class.forName(contractName).asSubclass(P8eContract::class.java) } override fun setupContract( From 03f70e51a2e4fd8674b1371bd4db16b9cec540b4 Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Tue, 26 Apr 2022 11:21:57 -0700 Subject: [PATCH 05/10] Contracts running --- dc.sh | 18 ++++++++++-------- service/docker/bootstrap.env | 4 ++-- service/docker/dependencies.yaml | 6 +++--- service/docker/prov-init/config/genesis.json | 4 ++-- .../domain/usecase/cee/ExecuteContract.kt | 9 +++++++++ .../domain/usecase/objectStore/GetAsset.kt | 11 +++++++++++ .../frameworks/cee/P8eContractService.kt | 5 ----- .../frameworks/provenance/ProvenanceService.kt | 4 ++-- .../extensions/ProvenanceExtensions.kt | 6 ++++-- 9 files changed, 43 insertions(+), 24 deletions(-) diff --git a/dc.sh b/dc.sh index 6296f1a6..f697b3e3 100755 --- a/dc.sh +++ b/dc.sh @@ -23,13 +23,13 @@ function up { sleep 2 sh service/docker/vault/init-and-unseal.sh 'http://127.0.0.1:8200' 'kv2_originations' sh service/docker/vault/add-secret.sh 'http://127.0.0.1:8200' 'kv2_originations' deadbeef-face-479b-860c-facefaceface \ - 0A4104F43FD6CD0DA184A666D444A4359EB9D38E06DB1EDC97B221DF90ED8189CFB8476EE2BF633DE0B4560F0D2BA284696C02ED31ADB32F09DEBE8D8906AA3E2BE71A \ - 0A410469BE2EC4699803FB7B49077F1CE0C88E2D2D41D23661EB1F420A72AA2B8DDF4325B349208B7F348C108B7C145FAEF41BB68FF338A75810522A89323E54BE91A6 \ - 0A4104DB326CF64C7466C2D63A2CD2C0401D1D6F8583C5F837C7510205DFB5CFA89D2115D0A3E0930D5FA01ACC664F1A182E1C0B43099D689B579849DEDDA1C63D0CF7 \ - 0A2009ABB890B396449706BB5998EEC6F6B0C795297B391A4BC2CF227B263555FF15 \ - 0A200B221F389D9B8E4964A8EB66F4EC07F83FCDD2E9DCE79B356FDDBE97767CF11C \ - 0A2100F5FE00731E3BC71F22CF054712A7C1F9A610848FC04BA81E6822D82D82C3562E \ - "jealous bright oyster fluid guide talent crystal minor modify broken stove spoon pen thank action smart enemy chunk ladder soon focus recall elite pulp" + 0A4104C51E49E4F0ABA2FD5B8CF99445D6D6C385164DBC8F35E7374CAC241D4155ADC48EF9B199F799DC865EC24AF54376CF5DD29A1287F1FD3410709A62F5DDE49349 \ + 0A4104C51E49E4F0ABA2FD5B8CF99445D6D6C385164DBC8F35E7374CAC241D4155ADC48EF9B199F799DC865EC24AF54376CF5DD29A1287F1FD3410709A62F5DDE49349 \ + 0A4104C51E49E4F0ABA2FD5B8CF99445D6D6C385164DBC8F35E7374CAC241D4155ADC48EF9B199F799DC865EC24AF54376CF5DD29A1287F1FD3410709A62F5DDE49349 \ + 0A201AD27E627DD0A6A5816D293C41DF801D3E7BA868EEC0F433FDA581D71E38016E \ + 0A201AD27E627DD0A6A5816D293C41DF801D3E7BA868EEC0F433FDA581D71E38016E \ + 0A201AD27E627DD0A6A5816D293C41DF801D3E7BA868EEC0F433FDA581D71E38016E \ + "stable payment cliff fault abuse clinic bus belt film then forward world goose bring picnic rich special brush basic lamp window coral worry change" sh service/docker/vault/add-secret.sh 'http://127.0.0.1:8200' 'kv2_originations' deadbeef-face-2222-860c-facefaceface \ 0A4104F43FD6CD0DA184A666D444A4359EB9D38E06DB1EDC97B221DF90ED8189CFB8476EE2BF633DE0B4560F0D2BA284696C02ED31ADB32F09DEBE8D8906AA3E2BE71A \ @@ -52,9 +52,11 @@ function publish() { source ./service/docker/bootstrap.env export FULL_PATH=$(realpath $PATH_TO_CONTRACTS) + echo $SIGNING_PRIVATE_KEY + echo $ENCRYPTION_PRIVATE_KEY if [[ -d "$FULL_PATH" ]]; then pushd $PATH_TO_CONTRACTS > /dev/null - ./gradlew p8eClean p8eCheck p8eBootstrap publishToMavenLocal -xsignMavenPublication --info + ./gradlew p8eClean p8eCheck p8eBootstrap --info && ./gradlew publishToMavenLocal -xsignMavenPublication --info popd > /dev/null else echo "Invalid path. Provide a valid path to the contracts directory you wish to publish." diff --git a/service/docker/bootstrap.env b/service/docker/bootstrap.env index 19a3d417..f3bd9e8c 100644 --- a/service/docker/bootstrap.env +++ b/service/docker/bootstrap.env @@ -1,8 +1,8 @@ # Export a mnemonic, private key, and address that can be used for provenance transactions and contract execution export CHAINCODE_MNEMONIC_1="stable payment cliff fault abuse clinic bus belt film then forward world goose bring picnic rich special brush basic lamp window coral worry change" -export PRIVATE_KEY_1="0A2100EF4A9391903BFE252CB240DA6695BC5F680A74A8E16BEBA003833DFE9B18C147" -export ADDRESS_1="tp1hslffrztjp399d86a25fh2khg0c6je3achzhyj" +export PRIVATE_KEY_1="0A201AD27E627DD0A6A5816D293C41DF801D3E7BA868EEC0F433FDA581D71E38016E" +export ADDRESS_1="tp1s2c62ke0mmwhqxguf7e2pt6e98yq38m4atwhwl" # p8e contract bootstrapping - signing and encryption keys are the same and match the private key above diff --git a/service/docker/dependencies.yaml b/service/docker/dependencies.yaml index 37196e79..5ece6b3d 100644 --- a/service/docker/dependencies.yaml +++ b/service/docker/dependencies.yaml @@ -26,7 +26,7 @@ services: image: ghcr.io/provenance-io/object-store:0.7.0 container_name: object-store-1 depends_on: - - postgres + - postgres-cee env_file: - object-store-1.env networks: @@ -40,7 +40,7 @@ services: image: ghcr.io/provenance-io/object-store:0.7.0 container_name: object-store-2 depends_on: - - postgres + - postgres-cee env_file: - object-store-2.env networks: @@ -52,7 +52,7 @@ services: provenance: image: provenanceio/provenance:v1.8.0-rc9 - container_name: provenance-cee + container_name: provenance command: bash -c "cp -rn /home/provenance_seed/* /home/provenance && /usr/bin/provenanced -t --home /home/provenance start" networks: - p8e-network diff --git a/service/docker/prov-init/config/genesis.json b/service/docker/prov-init/config/genesis.json index 6d02adf9..beab0e68 100644 --- a/service/docker/prov-init/config/genesis.json +++ b/service/docker/prov-init/config/genesis.json @@ -88,7 +88,7 @@ }, { "@type": "/cosmos.auth.v1beta1.BaseAccount", - "address": "tp1hslffrztjp399d86a25fh2khg0c6je3achzhyj", + "address": "tp1s2c62ke0mmwhqxguf7e2pt6e98yq38m4atwhwl", "pub_key": null, "account_number": "0", "sequence": "0" @@ -184,7 +184,7 @@ ] }, { - "address": "tp1hslffrztjp399d86a25fh2khg0c6je3achzhyj", + "address": "tp1s2c62ke0mmwhqxguf7e2pt6e98yq38m4atwhwl", "coins": [ { "denom": "nhash", diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt index 2241d47c..d6277463 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt @@ -1,6 +1,8 @@ package io.provenance.onboarding.domain.usecase.cee import io.provenance.core.KeyType +import io.provenance.hdwallet.ec.extensions.toJavaECPrivateKey +import io.provenance.hdwallet.ec.extensions.toJavaECPublicKey import io.provenance.onboarding.domain.cee.ContractService import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.AbstractUseCase @@ -10,8 +12,10 @@ import io.provenance.onboarding.domain.usecase.provenance.account.GetAccount import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils import io.provenance.scope.contract.proto.Specifications import io.provenance.scope.encryption.model.DirectKeyRef +import io.provenance.scope.encryption.util.toHex import io.provenance.scope.encryption.util.toJavaPrivateKey import io.provenance.scope.encryption.util.toJavaPublicKey +import io.provenance.scope.objectstore.util.toHex import io.provenance.scope.sdk.Affiliate import io.provenance.scope.sdk.Client import io.provenance.scope.sdk.ClientConfig @@ -19,8 +23,10 @@ import io.provenance.scope.sdk.SharedClient import java.net.URI import java.security.KeyPair import java.util.concurrent.TimeUnit +import mu.KotlinLogging import org.springframework.stereotype.Component +private val log = KotlinLogging.logger { } @Component class ExecuteContract( private val getOriginator: GetOriginator, @@ -57,6 +63,9 @@ class ExecuteContract( val client = Client(sharedClient, affiliate) val account = getAccount.execute(args.account) + log.info(account.keyPair.privateKey.toJavaECPrivateKey().toHex()) + log.info(account.keyPair.publicKey.toJavaECPublicKey().toHex()) + log.info(account.address.toString()) val contract = contractService.getContract(args.contractName) val session = contractService.setupContract(client, contract, emptyMap(), args.scopeUuid, args.sessionUuid) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt index 6d78d524..0bcb62ef 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt @@ -1,19 +1,25 @@ package io.provenance.onboarding.domain.usecase.objectStore import io.provenance.core.KeyType +import io.provenance.hdwallet.ec.extensions.toJavaECPublicKey import io.provenance.onboarding.domain.objectStore.ObjectStore import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.objectStore.model.GetAssetRequest import io.provenance.onboarding.frameworks.config.ObjectStoreConfig +import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils import io.provenance.scope.encryption.util.toJavaPrivateKey import io.provenance.scope.encryption.util.toJavaPublicKey import io.provenance.scope.objectstore.client.OsClient import io.provenance.scope.objectstore.util.base64Decode +import io.provenance.scope.objectstore.util.toHex import org.springframework.stereotype.Component import tech.figure.asset.v1beta1.Asset import java.lang.IllegalStateException import java.net.URI +import mu.KotlinLogging + +private val log = KotlinLogging.logger { } @Component class GetAsset( @@ -22,6 +28,11 @@ class GetAsset( private val objectStoreConfig: ObjectStoreConfig, ) : AbstractUseCase() { override suspend fun execute(args: GetAssetRequest): String { + + val utils = ProvenanceUtils() + val account = utils.getAccount("stable payment cliff fault abuse clinic bus belt film then forward world goose bring picnic rich special brush basic lamp window coral worry change", true, 0, 0) + log.info(account.keyPair.publicKey.toJavaECPublicKey().toHex()) + val originator = getOriginator.execute(args.originatorUuid) val osClient = OsClient(URI.create(args.objectStoreAddress), objectStoreConfig.timeoutMs) val publicKey = (originator.keys[KeyType.ENCRYPTION_PUBLIC_KEY] as? String)?.toJavaPublicKey() diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt index c54a01d6..d71132a2 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt @@ -5,18 +5,13 @@ import cosmos.base.abci.v1beta1.Abci import io.provenance.client.grpc.Signer import io.provenance.onboarding.domain.cee.ContractService import io.provenance.onboarding.frameworks.provenance.SingleTx -import io.provenance.scope.contract.contracts.ContractHash import io.provenance.scope.contract.spec.P8eContract import io.provenance.scope.loan.LoanScopeSpecification -import io.provenance.scope.loan.utility.LoanPackageContract import io.provenance.scope.sdk.Client import io.provenance.scope.sdk.Session import io.provenance.scope.sdk.SignedResult -import java.util.ServiceLoader import java.util.UUID import mu.KotlinLogging -import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider -import org.springframework.core.type.filter.AnnotationTypeFilter import org.springframework.stereotype.Component @Component diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt index 50c1d8c9..31eced5f 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt @@ -48,13 +48,13 @@ class ProvenanceService : Provenance { log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] Building the tx.") val messages = tx.value.messages.map { Any.pack(it, "") } val txBody = TxOuterClass.TxBody.newBuilder() - .setTimeoutHeight(pbClient.tendermintService.getCurrentHeight() + 12L) + .setTimeoutHeight(getCurrentHeight(pbClient) + 12L) .addAllMessages(messages) .build() log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] Determining account information for the tx.") val cachedOffset = cachedSequenceMap.getOrPut(signer.address()) { CachedAccountSequence() } - val account = pbClient.authClient.getBaseAccount(signer.address()) + val account = getBaseAccount(pbClient, signer.address()) val baseSigner = BaseReqSigner( signer, account = account, diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt index 7ba4b3b1..e183f337 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt @@ -4,9 +4,11 @@ import cosmos.auth.v1beta1.Auth import cosmos.base.abci.v1beta1.Abci.TxResponse import cosmos.base.tendermint.v1beta1.Query import cosmos.tx.v1beta1.ServiceOuterClass.BroadcastTxResponse +import io.provenance.client.grpc.PbClient import io.provenance.onboarding.frameworks.provenance.SingleTx import io.provenance.scope.contract.proto.Contracts import java.util.concurrent.TimeUnit +import io.provenance.client.protobuf.extensions.getBaseAccount fun BroadcastTxResponse.isError() = txResponse.isError() @@ -24,10 +26,10 @@ fun cosmos.tx.v1beta1.ServiceGrpc.ServiceBlockingStub.getTx(hash: String) = this .getTx(cosmos.tx.v1beta1.ServiceOuterClass.GetTxRequest.newBuilder().setHash(hash).build()) .txResponse -fun cosmos.base.tendermint.v1beta1.ServiceGrpc.ServiceBlockingStub.getCurrentHeight(): Long = this +fun getCurrentHeight(pbClient: PbClient): Long = pbClient.tendermintService .withDeadlineAfter(10, TimeUnit.SECONDS) .getLatestBlock(Query.GetLatestBlockRequest.getDefaultInstance()).block.header.height -fun cosmos.auth.v1beta1.QueryGrpc.QueryBlockingStub.getBaseAccount(address: String): Auth.BaseAccount = this +fun getBaseAccount(pbClient: PbClient, address: String): Auth.BaseAccount = pbClient.authClient .withDeadlineAfter(10, TimeUnit.SECONDS) .getBaseAccount(address) From e0093d8e4a2a84c7b30b600fed03928757c26247 Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Wed, 27 Apr 2022 10:09:01 -0700 Subject: [PATCH 06/10] pulling input annotation --- buildSrc/src/main/kotlin/Dependencies.kt | 5 +- service/build.gradle.kts | 1 + .../domain/usecase/cee/ExecuteContract.kt | 73 +++++++++++++------ .../cee/model/ExecuteContractConfig.kt | 16 ++++ .../cee/model/ExecuteContractRequest.kt | 14 +--- 5 files changed, 74 insertions(+), 35 deletions(-) create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 68caaaf6..0df4e295 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -37,9 +37,10 @@ object Versions { const val ProvenanceClient = "1.1.1" const val Unirest = "3.13.6" const val KeyAccessLib = "0.2.+" - const val LoanPackage = "0.1.+" + const val LoanPackage = "0.1.8" const val Grpc = "1.45.0" const val ProvenanceProto = "1.8.0" + const val Reflections = "0.9.10" } object Plugins { // please keep this sorted in sections @@ -201,6 +202,8 @@ object Dependencies { object Swagger { val Annotations = DependencySpec("io.swagger:swagger-annotations", Versions.Swagger) } + + val Reflections = DependencySpec("org.reflections:reflections", Versions.Reflections) } data class PluginSpec( diff --git a/service/build.gradle.kts b/service/build.gradle.kts index a07477ea..a27b3b32 100644 --- a/service/build.gradle.kts +++ b/service/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { Dependencies.Kong.Unirest, Dependencies.Grpc.Protobuf, Dependencies.Grpc.Stub, + Dependencies.Reflections, ).forEach { dep -> dep.implementation(this) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt index d6277463..490e3102 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt @@ -1,8 +1,8 @@ package io.provenance.onboarding.domain.usecase.cee +import com.google.protobuf.Message +import com.google.protobuf.util.JsonFormat import io.provenance.core.KeyType -import io.provenance.hdwallet.ec.extensions.toJavaECPrivateKey -import io.provenance.hdwallet.ec.extensions.toJavaECPublicKey import io.provenance.onboarding.domain.cee.ContractService import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.AbstractUseCase @@ -10,23 +10,28 @@ import io.provenance.onboarding.domain.usecase.cee.model.ExecuteContractRequest import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.provenance.account.GetAccount import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils +import io.provenance.onboarding.util.toPrettyJson +import io.provenance.scope.contract.annotations.Input import io.provenance.scope.contract.proto.Specifications import io.provenance.scope.encryption.model.DirectKeyRef -import io.provenance.scope.encryption.util.toHex import io.provenance.scope.encryption.util.toJavaPrivateKey import io.provenance.scope.encryption.util.toJavaPublicKey -import io.provenance.scope.objectstore.util.toHex import io.provenance.scope.sdk.Affiliate import io.provenance.scope.sdk.Client import io.provenance.scope.sdk.ClientConfig import io.provenance.scope.sdk.SharedClient import java.net.URI +import io.provenance.scope.contract.annotations.Record +import io.provenance.scope.contract.spec.P8eContract import java.security.KeyPair import java.util.concurrent.TimeUnit +import kotlin.reflect.full.functions +import kotlin.reflect.full.primaryConstructor import mu.KotlinLogging import org.springframework.stereotype.Component -private val log = KotlinLogging.logger { } +private val log = KotlinLogging.logger { } + @Component class ExecuteContract( private val getOriginator: GetOriginator, @@ -34,17 +39,26 @@ class ExecuteContract( private val provenanceService: Provenance, private val getAccount: GetAccount ) : AbstractUseCase() { + override suspend fun execute(args: ExecuteContractRequest) { val utils = ProvenanceUtils() + val account = getAccount.execute(args.config.account) + val originator = getOriginator.execute(args.config.account.originatorUuid) + val affiliate = Affiliate( + signingKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), + encryptionKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), + Specifications.PartyType.valueOf(args.config.partyType), + ) + val sharedClient = SharedClient( ClientConfig( - mainNet = !args.isTestNet, + mainNet = !args.config.isTestNet, cacheJarSizeInBytes = 4L * 1024 * 1024, // ~ 4 MB, cacheRecordSizeInBytes = 0L, cacheSpecSizeInBytes = 0L, - disableContractLogs = !args.isTestNet, + disableContractLogs = !args.config.isTestNet, osConcurrencySize = 6, - osGrpcUrl = URI(args.objectStoreUrl), + osGrpcUrl = URI(args.config.objectStoreUrl), osChannelCustomizeFn = { channelBuilder -> channelBuilder .idleTimeout(1, TimeUnit.MINUTES) @@ -54,25 +68,40 @@ class ExecuteContract( ) ) - val originator = getOriginator.execute(args.account.originatorUuid) - val affiliate = Affiliate( - signingKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), - encryptionKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), - Specifications.PartyType.valueOf(args.partyType), - ) + val contract = contractService.getContract(args.config.contractName) + val records = getRecords(args.records, contract) val client = Client(sharedClient, affiliate) - val account = getAccount.execute(args.account) - log.info(account.keyPair.privateKey.toJavaECPrivateKey().toHex()) - log.info(account.keyPair.publicKey.toJavaECPublicKey().toHex()) - log.info(account.address.toString()) - - val contract = contractService.getContract(args.contractName) - val session = contractService.setupContract(client, contract, emptyMap(), args.scopeUuid, args.sessionUuid) + val session = contractService.setupContract(client, contract, records, args.config.scopeUuid, args.config.sessionUuid) val signer = utils.getSigner(account) contractService.executeContract(client, signer, contract, session) { tx -> - provenanceService.executeTransaction(args.chainId, args.nodeEndpoint, session, tx, signer) + provenanceService.executeTransaction(args.config.chainId, args.config.nodeEndpoint, session, tx, signer) + } + } + + private fun getRecords(records: Map, contract: Class): Map { + val contractRecords = mutableMapOf() + + try { + contract.kotlin.functions.forEach { func -> + func.parameters.forEach { param -> + + val parameterClass = Class.forName(param.type.toString()) + val builder = parameterClass.getMethod("newBuilder").invoke(null) as Message.Builder + + val input = param.annotations.filter { it is Input }.singleOrNull() as Input + val record = records.getOrDefault(input.name, null) + ?: throw IllegalStateException("Contract required input record with name ${input.name} but none was found!") + + JsonFormat.parser().merge(record.toPrettyJson(), builder) + contractRecords[input.name] = builder.build() + } + } + } catch (ex: Exception) { + log.error("Failed to get inputs for contract ${contract}") } + + return contractRecords } } diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt new file mode 100644 index 00000000..e4cedb6b --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt @@ -0,0 +1,16 @@ +package io.provenance.onboarding.domain.usecase.cee.model + +import io.provenance.onboarding.domain.usecase.common.model.AccountInfo +import java.util.UUID + +data class ExecuteContractConfig( + val contractName: String, + val scopeUuid: UUID, + val sessionUuid: UUID, + val objectStoreUrl: String, + val partyType: String, + val isTestNet: Boolean, + val account: AccountInfo, + val chainId: String, + val nodeEndpoint: String, +) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt index 50c39161..249c6f50 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt @@ -1,16 +1,6 @@ package io.provenance.onboarding.domain.usecase.cee.model -import io.provenance.onboarding.domain.usecase.common.model.AccountInfo -import java.util.UUID - data class ExecuteContractRequest( - val contractName: String, - val scopeUuid: UUID, - val sessionUuid: UUID, - val objectStoreUrl: String, - val partyType: String, - val isTestNet: Boolean, - val account: AccountInfo, - val chainId: String, - val nodeEndpoint: String + val config: ExecuteContractConfig, + val records: Map ) From 02c8bbb918e35d736929c25a47e5f8ae00c5b62d Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Wed, 27 Apr 2022 14:52:52 -0700 Subject: [PATCH 07/10] Input parsers + cleanup --- .../onboarding/domain/cee/ContractParser.kt | 7 +++ .../onboarding/domain/cee/ContractService.kt | 3 +- .../onboarding/domain/cee/InputParser.kt | 8 +++ .../domain/provenance/Provenance.kt | 7 ++- .../domain/usecase/cee/ExecuteContract.kt | 62 ++++++++++--------- .../domain/usecase/cee/model/ClientConfig.kt | 5 ++ .../usecase/cee/model/ContractConfig.kt | 9 +++ .../cee/model/ExecuteContractConfig.kt | 13 ++-- .../usecase/common/model/AccountInfo.kt | 2 + .../usecase/common/model/ProvenanceConfig.kt | 7 +++ .../model/TxResponse.kt} | 4 +- .../domain/usecase/objectStore/GetAsset.kt | 2 +- .../provenance/tx/CreateTxOnboardAsset.kt | 6 +- .../domain/usecase/provenance/tx/ExecuteTx.kt | 6 +- .../frameworks/cee/ContractParserService.kt | 16 +++++ .../frameworks/cee/P8eContractService.kt | 12 +--- .../frameworks/cee/parsers/MessageParser.kt | 18 ++++++ .../provenance/ProvenanceService.kt | 13 ++-- 18 files changed, 133 insertions(+), 67 deletions(-) create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/cee/InputParser.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ClientConfig.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ContractConfig.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/ProvenanceConfig.kt rename service/src/main/kotlin/io/provenance/onboarding/domain/usecase/{provenance/tx/model/OnboardAssetResponse.kt => common/model/TxResponse.kt} (50%) create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt create mode 100644 service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/parsers/MessageParser.kt diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt new file mode 100644 index 00000000..99b8e554 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt @@ -0,0 +1,7 @@ +package io.provenance.onboarding.domain.cee + +import com.google.protobuf.Message + +interface ContractParser { + fun parse(input: Any, type: Class<*>): Message +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt index 1239399e..29375085 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt @@ -2,7 +2,6 @@ package io.provenance.onboarding.domain.cee import com.google.protobuf.Message import cosmos.base.abci.v1beta1.Abci -import io.provenance.client.grpc.Signer import io.provenance.onboarding.frameworks.provenance.SingleTx import io.provenance.scope.contract.spec.P8eContract import io.provenance.scope.sdk.Client @@ -12,5 +11,5 @@ import java.util.UUID interface ContractService { fun getContract(contractName: String): Class fun setupContract(client: Client, contractClass: Class, records: Map, scopeUuid: UUID, sessionUuid: UUID? = null): Session - fun executeContract(client: Client, signer: Signer, contractClass: Class, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse) + fun executeContract(client: Client, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse): Result } diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/InputParser.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/InputParser.kt new file mode 100644 index 00000000..60a7e140 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/InputParser.kt @@ -0,0 +1,8 @@ +package io.provenance.onboarding.domain.cee + +import com.google.protobuf.Message + +interface InputParser { + val type: Class<*> + fun parse(input: Any, type: Class<*>): Message +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt index 4a0ec284..a9887064 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt @@ -3,12 +3,13 @@ package io.provenance.onboarding.domain.provenance import cosmos.base.abci.v1beta1.Abci import io.provenance.client.grpc.Signer import io.provenance.hdwallet.wallet.Account +import io.provenance.onboarding.domain.usecase.common.model.ProvenanceConfig import io.provenance.onboarding.domain.usecase.common.model.TxBody -import io.provenance.onboarding.domain.usecase.provenance.tx.model.OnboardAssetResponse +import io.provenance.onboarding.domain.usecase.common.model.TxResponse import io.provenance.onboarding.frameworks.provenance.ProvenanceTx import io.provenance.scope.sdk.Session interface Provenance { - fun onboard(chainId: String, nodeEndpoint: String, account: Account, storeTxBody: TxBody): OnboardAssetResponse - fun executeTransaction(chainId: String, nodeEndpoint: String, session: Session, tx: ProvenanceTx, signer: Signer): Abci.TxResponse + fun onboard(chainId: String, nodeEndpoint: String, account: Account, storeTxBody: TxBody): TxResponse + fun executeTransaction(config: ProvenanceConfig, session: Session, tx: ProvenanceTx, signer: Signer): Abci.TxResponse } diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt index 490e3102..292d7678 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt @@ -1,18 +1,17 @@ package io.provenance.onboarding.domain.usecase.cee import com.google.protobuf.Message -import com.google.protobuf.util.JsonFormat import io.provenance.core.KeyType +import io.provenance.onboarding.domain.cee.ContractParser import io.provenance.onboarding.domain.cee.ContractService import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.cee.model.ExecuteContractRequest +import io.provenance.onboarding.domain.usecase.common.model.TxResponse import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.provenance.account.GetAccount import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils -import io.provenance.onboarding.util.toPrettyJson import io.provenance.scope.contract.annotations.Input -import io.provenance.scope.contract.proto.Specifications import io.provenance.scope.encryption.model.DirectKeyRef import io.provenance.scope.encryption.util.toJavaPrivateKey import io.provenance.scope.encryption.util.toJavaPublicKey @@ -21,12 +20,10 @@ import io.provenance.scope.sdk.Client import io.provenance.scope.sdk.ClientConfig import io.provenance.scope.sdk.SharedClient import java.net.URI -import io.provenance.scope.contract.annotations.Record import io.provenance.scope.contract.spec.P8eContract import java.security.KeyPair import java.util.concurrent.TimeUnit import kotlin.reflect.full.functions -import kotlin.reflect.full.primaryConstructor import mu.KotlinLogging import org.springframework.stereotype.Component @@ -37,28 +34,29 @@ class ExecuteContract( private val getOriginator: GetOriginator, private val contractService: ContractService, private val provenanceService: Provenance, - private val getAccount: GetAccount -) : AbstractUseCase() { + private val getAccount: GetAccount, + private val contractInputParser: ContractParser, +) : AbstractUseCase() { - override suspend fun execute(args: ExecuteContractRequest) { + override suspend fun execute(args: ExecuteContractRequest): TxResponse { val utils = ProvenanceUtils() val account = getAccount.execute(args.config.account) val originator = getOriginator.execute(args.config.account.originatorUuid) val affiliate = Affiliate( signingKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), encryptionKeyRef = DirectKeyRef(KeyPair(originator.keys[KeyType.SIGNING_PUBLIC_KEY].toString().toJavaPublicKey(), originator.keys[KeyType.SIGNING_PRIVATE_KEY].toString().toJavaPrivateKey())), - Specifications.PartyType.valueOf(args.config.partyType), + args.config.account.partyType, ) val sharedClient = SharedClient( ClientConfig( - mainNet = !args.config.isTestNet, + mainNet = !args.config.account.isTestNet, cacheJarSizeInBytes = 4L * 1024 * 1024, // ~ 4 MB, cacheRecordSizeInBytes = 0L, cacheSpecSizeInBytes = 0L, - disableContractLogs = !args.config.isTestNet, + disableContractLogs = !args.config.account.isTestNet, osConcurrencySize = 6, - osGrpcUrl = URI(args.config.objectStoreUrl), + osGrpcUrl = URI(args.config.client.objectStoreUrl), osChannelCustomizeFn = { channelBuilder -> channelBuilder .idleTimeout(1, TimeUnit.MINUTES) @@ -68,38 +66,46 @@ class ExecuteContract( ) ) - val contract = contractService.getContract(args.config.contractName) + val contract = contractService.getContract(args.config.contract.contractName) val records = getRecords(args.records, contract) val client = Client(sharedClient, affiliate) - val session = contractService.setupContract(client, contract, records, args.config.scopeUuid, args.config.sessionUuid) + val session = contractService.setupContract(client, contract, records, args.config.contract.scopeUuid, args.config.contract.sessionUuid) val signer = utils.getSigner(account) - contractService.executeContract(client, signer, contract, session) { tx -> - provenanceService.executeTransaction(args.config.chainId, args.config.nodeEndpoint, session, tx, signer) - } + contractService.executeContract(client, session) { tx -> + provenanceService.executeTransaction(args.config.provenanceConfig, session, tx, signer) + }.fold( + onSuccess = { result -> + log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contract.simpleName} is pending. The tx hash is ${result.txhash}.") + return TxResponse(result.txhash, result.gasWanted.toString(), result.gasUsed.toString(), result.height.toString()) + }, + onFailure = { throwable -> + log.error("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contract.simpleName} has failed execution. An error occurred.", throwable) + throw throwable + } + ) } + @Suppress("TooGenericExceptionCaught") private fun getRecords(records: Map, contract: Class): Map { val contractRecords = mutableMapOf() try { contract.kotlin.functions.forEach { func -> func.parameters.forEach { param -> - - val parameterClass = Class.forName(param.type.toString()) - val builder = parameterClass.getMethod("newBuilder").invoke(null) as Message.Builder - - val input = param.annotations.filter { it is Input }.singleOrNull() as Input - val record = records.getOrDefault(input.name, null) - ?: throw IllegalStateException("Contract required input record with name ${input.name} but none was found!") - - JsonFormat.parser().merge(record.toPrettyJson(), builder) - contractRecords[input.name] = builder.build() + (param.annotations.firstOrNull { it is Input } as? Input)?.let { input -> + val parameterClass = Class.forName(param.type.toString()) + val recordToParse = records.getOrDefault(input.name, null) + ?: throw IllegalStateException("Contract required input record with name ${input.name} but none was found!") + val record = contractInputParser.parse(recordToParse, parameterClass) + contractRecords[input.name] = record + } } } } catch (ex: Exception) { - log.error("Failed to get inputs for contract ${contract}") + log.error("Failed to get inputs for contract ${contract.simpleName}") + throw ex } return contractRecords diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ClientConfig.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ClientConfig.kt new file mode 100644 index 00000000..ec0430e1 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ClientConfig.kt @@ -0,0 +1,5 @@ +package io.provenance.onboarding.domain.usecase.cee.model + +data class ClientConfig( + val objectStoreUrl: String, +) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ContractConfig.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ContractConfig.kt new file mode 100644 index 00000000..44462995 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ContractConfig.kt @@ -0,0 +1,9 @@ +package io.provenance.onboarding.domain.usecase.cee.model + +import java.util.UUID + +data class ContractConfig( + val contractName: String, + val scopeUuid: UUID, + val sessionUuid: UUID?, +) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt index e4cedb6b..fd661aca 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt @@ -1,16 +1,11 @@ package io.provenance.onboarding.domain.usecase.cee.model import io.provenance.onboarding.domain.usecase.common.model.AccountInfo -import java.util.UUID +import io.provenance.onboarding.domain.usecase.common.model.ProvenanceConfig data class ExecuteContractConfig( - val contractName: String, - val scopeUuid: UUID, - val sessionUuid: UUID, - val objectStoreUrl: String, - val partyType: String, - val isTestNet: Boolean, + val contract: ContractConfig, + val client: ClientConfig, val account: AccountInfo, - val chainId: String, - val nodeEndpoint: String, + val provenanceConfig: ProvenanceConfig, ) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/AccountInfo.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/AccountInfo.kt index 93bc5611..601a6126 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/AccountInfo.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/AccountInfo.kt @@ -1,5 +1,6 @@ package io.provenance.onboarding.domain.usecase.common.model +import io.provenance.scope.contract.proto.Specifications import java.util.UUID data class AccountInfo( @@ -7,4 +8,5 @@ data class AccountInfo( val keyRingIndex: Int = 0, val keyIndex: Int = 0, val isTestNet: Boolean = true, + val partyType: Specifications.PartyType = Specifications.PartyType.OWNER, ) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/ProvenanceConfig.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/ProvenanceConfig.kt new file mode 100644 index 00000000..fa393ec7 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/ProvenanceConfig.kt @@ -0,0 +1,7 @@ +package io.provenance.onboarding.domain.usecase.common.model + +data class ProvenanceConfig( + val chainId: String, + val nodeEndpoint: String, + val gasAdjustment: Double? = 1.5, +) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/model/OnboardAssetResponse.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/TxResponse.kt similarity index 50% rename from service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/model/OnboardAssetResponse.kt rename to service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/TxResponse.kt index cd96709e..805a7ad3 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/model/OnboardAssetResponse.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/common/model/TxResponse.kt @@ -1,6 +1,6 @@ -package io.provenance.onboarding.domain.usecase.provenance.tx.model +package io.provenance.onboarding.domain.usecase.common.model -data class OnboardAssetResponse( +data class TxResponse( val hash: String, val gasWanted: String, val gasUsed: String, diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt index 0bcb62ef..75b0bcca 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt @@ -19,7 +19,7 @@ import java.lang.IllegalStateException import java.net.URI import mu.KotlinLogging -private val log = KotlinLogging.logger { } +private val log = KotlinLogging.logger { } @Component class GetAsset( diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/CreateTxOnboardAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/CreateTxOnboardAsset.kt index f56c9a61..aaf60e77 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/CreateTxOnboardAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/CreateTxOnboardAsset.kt @@ -4,7 +4,7 @@ import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.provenance.account.GetAccount import io.provenance.onboarding.domain.usecase.provenance.tx.model.CreateTxOnboardAssetRequest -import io.provenance.onboarding.domain.usecase.provenance.tx.model.OnboardAssetResponse +import io.provenance.onboarding.domain.usecase.common.model.TxResponse import org.springframework.stereotype.Component @Component @@ -12,8 +12,8 @@ class CreateTxOnboardAsset( private val provenance: Provenance, private val createOnboardTx: CreateTx, private val getAccount: GetAccount, -) : AbstractUseCase() { - override suspend fun execute(args: CreateTxOnboardAssetRequest): OnboardAssetResponse { +) : AbstractUseCase() { + override suspend fun execute(args: CreateTxOnboardAssetRequest): TxResponse { val account = getAccount.execute(args.txRequest.account) val tx = createOnboardTx.execute(args.txRequest) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/ExecuteTx.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/ExecuteTx.kt index f706f018..087112f1 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/ExecuteTx.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/provenance/tx/ExecuteTx.kt @@ -4,15 +4,15 @@ import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.provenance.account.GetAccount import io.provenance.onboarding.domain.usecase.provenance.tx.model.ExecuteTxRequest -import io.provenance.onboarding.domain.usecase.provenance.tx.model.OnboardAssetResponse +import io.provenance.onboarding.domain.usecase.common.model.TxResponse import org.springframework.stereotype.Component @Component class ExecuteTx( private val provenance: Provenance, private val getAccount: GetAccount, -) : AbstractUseCase() { - override suspend fun execute(args: ExecuteTxRequest): OnboardAssetResponse { +) : AbstractUseCase() { + override suspend fun execute(args: ExecuteTxRequest): TxResponse { val account = getAccount.execute(args.account) return provenance.onboard(args.chainId, args.nodeEndpoint, account, args.tx) } diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt new file mode 100644 index 00000000..fab50208 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt @@ -0,0 +1,16 @@ +package io.provenance.onboarding.frameworks.cee + +import com.google.protobuf.Message +import io.provenance.onboarding.domain.cee.ContractParser +import io.provenance.onboarding.domain.cee.InputParser +import kotlin.reflect.full.isSubclassOf +import org.springframework.stereotype.Component + +@Component +class ContractParserService( + private val parsers: List +) : ContractParser { + override fun parse(input: Any, type: Class<*>): Message = + parsers.firstOrNull { type.kotlin.isSubclassOf(it.type.kotlin) }?.parse(input, type) + ?: throw IllegalStateException("Failed to find parser for contract input.") +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt index d71132a2..aa509eda 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/P8eContractService.kt @@ -2,7 +2,6 @@ package io.provenance.onboarding.frameworks.cee import com.google.protobuf.Message import cosmos.base.abci.v1beta1.Abci -import io.provenance.client.grpc.Signer import io.provenance.onboarding.domain.cee.ContractService import io.provenance.onboarding.frameworks.provenance.SingleTx import io.provenance.scope.contract.spec.P8eContract @@ -37,20 +36,13 @@ class P8eContractService : ContractService { log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contractClass.simpleName} has been setup.") } - override fun executeContract(client: Client, signer: Signer, contractClass: Class, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse) = + override fun executeContract(client: Client, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse): Result = runCatching { when (val result = client.execute(session)) { is SignedResult -> executeTransaction(SingleTx(result)) else -> throw IllegalStateException("Must be a signed result since this is a single party contract.") } - }.fold( - onSuccess = { result -> - log.info("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contractClass.simpleName} is pending. The tx hash is ${result.txhash}.") - }, - onFailure = { throwable -> - log.error("[L: ${session.scopeUuid}, S: ${session.sessionUuid}] ${contractClass.simpleName} has failed execution. An error occurred.", throwable) - } - ) + } private fun Session.Builder.configureSession(records: Map, sessionUuid: UUID? = null): Session = this.setSessionUuid(sessionUuid ?: UUID.randomUUID()) diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/parsers/MessageParser.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/parsers/MessageParser.kt new file mode 100644 index 00000000..243cee6b --- /dev/null +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/parsers/MessageParser.kt @@ -0,0 +1,18 @@ +package io.provenance.onboarding.frameworks.cee.parsers + +import com.google.protobuf.Message +import com.google.protobuf.util.JsonFormat +import io.provenance.onboarding.domain.cee.InputParser +import io.provenance.onboarding.util.toPrettyJson +import org.springframework.stereotype.Component + +@Component +class MessageParser : InputParser { + override val type: Class<*> = Message::class.java + + override fun parse(input: Any, type: Class<*>): Message { + val builder = type.getMethod("newBuilder").invoke(null) as Message.Builder + JsonFormat.parser().merge(input.toPrettyJson(), builder) + return builder.build() + } +} diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt index 31eced5f..dc23fae6 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt @@ -11,8 +11,9 @@ import io.provenance.client.grpc.PbClient import io.provenance.client.grpc.Signer import io.provenance.hdwallet.wallet.Account import io.provenance.onboarding.domain.provenance.Provenance +import io.provenance.onboarding.domain.usecase.common.model.ProvenanceConfig import io.provenance.onboarding.domain.usecase.common.model.TxBody -import io.provenance.onboarding.domain.usecase.provenance.tx.model.OnboardAssetResponse +import io.provenance.onboarding.domain.usecase.common.model.TxResponse import io.provenance.onboarding.frameworks.provenance.exceptions.ContractExceptionException import io.provenance.onboarding.frameworks.provenance.extensions.getBaseAccount import io.provenance.onboarding.frameworks.provenance.extensions.getCurrentHeight @@ -38,8 +39,8 @@ class ProvenanceService : Provenance { private val log = KotlinLogging.logger { } private val cachedSequenceMap = ConcurrentHashMap() - override fun executeTransaction(chainId: String, nodeEndpoint: String, session: Session, tx: ProvenanceTx, signer: Signer): Abci.TxResponse { - val pbClient = PbClient(chainId, URI(nodeEndpoint), GasEstimationMethod.MSG_FEE_CALCULATION) + override fun executeTransaction(config: ProvenanceConfig, session: Session, tx: ProvenanceTx, signer: Signer): Abci.TxResponse { + val pbClient = PbClient(config.chainId, URI(config.nodeEndpoint), GasEstimationMethod.MSG_FEE_CALCULATION) return when (tx) { is SingleTx -> { @@ -65,7 +66,7 @@ class ProvenanceService : Provenance { val result = pbClient.estimateAndBroadcastTx( txBody = txBody, signers = listOf(baseSigner), - gasAdjustment = 1.5, + gasAdjustment = config.gasAdjustment, mode = ServiceOuterClass.BroadcastMode.BROADCAST_MODE_BLOCK ) @@ -82,7 +83,7 @@ class ProvenanceService : Provenance { } } - override fun onboard(chainId: String, nodeEndpoint: String, account: Account, storeTxBody: TxBody): OnboardAssetResponse { + override fun onboard(chainId: String, nodeEndpoint: String, account: Account, storeTxBody: TxBody): TxResponse { val pbClient = PbClient(chainId, URI(nodeEndpoint), GasEstimationMethod.MSG_FEE_CALCULATION) val utility = ProvenanceUtils() @@ -99,6 +100,6 @@ class ProvenanceService : Provenance { gasAdjustment = 1.5 ).txResponse - return OnboardAssetResponse(response.txhash, response.gasWanted.toString(), response.gasUsed.toString(), response.height.toString()) + return TxResponse(response.txhash, response.gasWanted.toString(), response.gasUsed.toString(), response.height.toString()) } } From 8545a21528df1dc79749362727c6fc1d22641ab4 Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Wed, 27 Apr 2022 15:03:42 -0700 Subject: [PATCH 08/10] additional cleanup --- .../onboarding/domain/cee/ContractParser.kt | 2 +- .../domain/usecase/cee/ExecuteContract.kt | 4 +-- .../domain/usecase/objectStore/GetAsset.kt | 11 ------- .../frameworks/cee/ContractParserService.kt | 2 +- .../provenance/exceptions/Exceptions.kt | 30 ------------------- 5 files changed, 4 insertions(+), 45 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt index 99b8e554..b6bed016 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt @@ -3,5 +3,5 @@ package io.provenance.onboarding.domain.cee import com.google.protobuf.Message interface ContractParser { - fun parse(input: Any, type: Class<*>): Message + fun parseInput(input: Any, type: Class<*>): Message } diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt index 292d7678..6a7a578d 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt @@ -35,7 +35,7 @@ class ExecuteContract( private val contractService: ContractService, private val provenanceService: Provenance, private val getAccount: GetAccount, - private val contractInputParser: ContractParser, + private val contractParser: ContractParser, ) : AbstractUseCase() { override suspend fun execute(args: ExecuteContractRequest): TxResponse { @@ -98,7 +98,7 @@ class ExecuteContract( val parameterClass = Class.forName(param.type.toString()) val recordToParse = records.getOrDefault(input.name, null) ?: throw IllegalStateException("Contract required input record with name ${input.name} but none was found!") - val record = contractInputParser.parse(recordToParse, parameterClass) + val record = contractParser.parseInput(recordToParse, parameterClass) contractRecords[input.name] = record } } diff --git a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt index 75b0bcca..6d78d524 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/domain/usecase/objectStore/GetAsset.kt @@ -1,25 +1,19 @@ package io.provenance.onboarding.domain.usecase.objectStore import io.provenance.core.KeyType -import io.provenance.hdwallet.ec.extensions.toJavaECPublicKey import io.provenance.onboarding.domain.objectStore.ObjectStore import io.provenance.onboarding.domain.usecase.AbstractUseCase import io.provenance.onboarding.domain.usecase.common.originator.GetOriginator import io.provenance.onboarding.domain.usecase.objectStore.model.GetAssetRequest import io.provenance.onboarding.frameworks.config.ObjectStoreConfig -import io.provenance.onboarding.frameworks.provenance.utility.ProvenanceUtils import io.provenance.scope.encryption.util.toJavaPrivateKey import io.provenance.scope.encryption.util.toJavaPublicKey import io.provenance.scope.objectstore.client.OsClient import io.provenance.scope.objectstore.util.base64Decode -import io.provenance.scope.objectstore.util.toHex import org.springframework.stereotype.Component import tech.figure.asset.v1beta1.Asset import java.lang.IllegalStateException import java.net.URI -import mu.KotlinLogging - -private val log = KotlinLogging.logger { } @Component class GetAsset( @@ -28,11 +22,6 @@ class GetAsset( private val objectStoreConfig: ObjectStoreConfig, ) : AbstractUseCase() { override suspend fun execute(args: GetAssetRequest): String { - - val utils = ProvenanceUtils() - val account = utils.getAccount("stable payment cliff fault abuse clinic bus belt film then forward world goose bring picnic rich special brush basic lamp window coral worry change", true, 0, 0) - log.info(account.keyPair.publicKey.toJavaECPublicKey().toHex()) - val originator = getOriginator.execute(args.originatorUuid) val osClient = OsClient(URI.create(args.objectStoreAddress), objectStoreConfig.timeoutMs) val publicKey = (originator.keys[KeyType.ENCRYPTION_PUBLIC_KEY] as? String)?.toJavaPublicKey() diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt index fab50208..f907a577 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/cee/ContractParserService.kt @@ -10,7 +10,7 @@ import org.springframework.stereotype.Component class ContractParserService( private val parsers: List ) : ContractParser { - override fun parse(input: Any, type: Class<*>): Message = + override fun parseInput(input: Any, type: Class<*>): Message = parsers.firstOrNull { type.kotlin.isSubclassOf(it.type.kotlin) }?.parse(input, type) ?: throw IllegalStateException("Failed to find parser for contract input.") } diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt index eacb5534..e4bc0717 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt @@ -1,33 +1,3 @@ package io.provenance.onboarding.frameworks.provenance.exceptions -import java.util.UUID - -open class CannotOnboardUnfundedLoanException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - open class ContractExceptionException(message: String? = "", val shouldRetry: Boolean = false, cause: Throwable? = null) : RuntimeException(message, cause) - -open class ContractInProgressException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class ContractRetryException(message: String? = "", val willRetry: Boolean = true, cause: Throwable? = null) : RuntimeException(message, cause) - -open class InsufficientFundsException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class InvalidFactException(message: String? = "", val factName: String? = null, cause: Throwable? = null) : RuntimeException(message, cause) - -open class InvalidLoanFactException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class InvalidLoanTypeException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class InvalidOriginatorException(message: String? = "", val originatorUuid: UUID? = null, cause: Throwable? = null) : RuntimeException(message, cause) - -open class NotificationException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class ResourceNotFoundException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class LoanAlreadyExistsException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class LoanFundingPaused(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class WontRunLoanValidationException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) - -open class ExistingScopeNotChangedException(message: String) : java.lang.RuntimeException(message) From 8342e5fa32d145418033dc8c5fd8556189503cfb Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Wed, 27 Apr 2022 15:04:53 -0700 Subject: [PATCH 09/10] lint --- .../frameworks/provenance/exceptions/Exceptions.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt index e4bc0717..670944a0 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt @@ -1,3 +1,9 @@ package io.provenance.onboarding.frameworks.provenance.exceptions open class ContractExceptionException(message: String? = "", val shouldRetry: Boolean = false, cause: Throwable? = null) : RuntimeException(message, cause) + +open class ResourceNotFoundException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class WontRunLoanValidationException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) + +open class ExistingScopeNotChangedException(message: String) : java.lang.RuntimeException(message) From 63ae091d980b92d268ac46778d04ca001f44fd9f Mon Sep 17 00:00:00 2001 From: Cody Worsnop Date: Wed, 27 Apr 2022 15:33:48 -0700 Subject: [PATCH 10/10] PR comments --- .../onboarding/frameworks/provenance/ProvenanceService.kt | 4 ++-- .../onboarding/frameworks/provenance/exceptions/Exceptions.kt | 4 ++-- .../frameworks/provenance/extensions/ProvenanceExtensions.kt | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt index dc23fae6..3508eab6 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/ProvenanceService.kt @@ -14,7 +14,7 @@ import io.provenance.onboarding.domain.provenance.Provenance import io.provenance.onboarding.domain.usecase.common.model.ProvenanceConfig import io.provenance.onboarding.domain.usecase.common.model.TxBody import io.provenance.onboarding.domain.usecase.common.model.TxResponse -import io.provenance.onboarding.frameworks.provenance.exceptions.ContractExceptionException +import io.provenance.onboarding.frameworks.provenance.exceptions.ContractTransactionException import io.provenance.onboarding.frameworks.provenance.extensions.getBaseAccount import io.provenance.onboarding.frameworks.provenance.extensions.getCurrentHeight import io.provenance.onboarding.frameworks.provenance.extensions.getErrorResult @@ -76,7 +76,7 @@ class ProvenanceService : Provenance { } result.txResponse } - else -> throw ContractExceptionException(error.result.errorMessage) + else -> throw ContractTransactionException(error.result.errorMessage) } } is BatchTx -> throw IllegalArgumentException("Batched transactions are not supported.") diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt index 670944a0..7061fd4c 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/exceptions/Exceptions.kt @@ -1,9 +1,9 @@ package io.provenance.onboarding.frameworks.provenance.exceptions -open class ContractExceptionException(message: String? = "", val shouldRetry: Boolean = false, cause: Throwable? = null) : RuntimeException(message, cause) +open class ContractTransactionException(message: String? = "", val shouldRetry: Boolean = false, cause: Throwable? = null) : RuntimeException(message, cause) open class ResourceNotFoundException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) open class WontRunLoanValidationException(message: String? = "", cause: Throwable? = null) : RuntimeException(message, cause) -open class ExistingScopeNotChangedException(message: String) : java.lang.RuntimeException(message) +open class ExistingScopeNotChangedException(message: String) : RuntimeException(message) diff --git a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt index e183f337..7981ce2a 100644 --- a/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt +++ b/service/src/main/kotlin/io/provenance/onboarding/frameworks/provenance/extensions/ProvenanceExtensions.kt @@ -22,10 +22,6 @@ fun TxResponse.getError(): String = fun SingleTx.getErrorResult() = this.value.envelopeState.result.contract.considerationsList.firstOrNull { it.result.result == Contracts.ExecutionResult.Result.FAIL } -fun cosmos.tx.v1beta1.ServiceGrpc.ServiceBlockingStub.getTx(hash: String) = this.withDeadlineAfter(10, TimeUnit.SECONDS) - .getTx(cosmos.tx.v1beta1.ServiceOuterClass.GetTxRequest.newBuilder().setHash(hash).build()) - .txResponse - fun getCurrentHeight(pbClient: PbClient): Long = pbClient.tendermintService .withDeadlineAfter(10, TimeUnit.SECONDS) .getLatestBlock(Query.GetLatestBlockRequest.getDefaultInstance()).block.header.height