-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from provenance-io/p8e-contract-execution
initial pass of contract work
- Loading branch information
Showing
40 changed files
with
501 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractParser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package io.provenance.onboarding.domain.cee | ||
|
||
import com.google.protobuf.Message | ||
|
||
interface ContractParser { | ||
fun parseInput(input: Any, type: Class<*>): Message | ||
} |
15 changes: 15 additions & 0 deletions
15
service/src/main/kotlin/io/provenance/onboarding/domain/cee/ContractService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package io.provenance.onboarding.domain.cee | ||
|
||
import com.google.protobuf.Message | ||
import cosmos.base.abci.v1beta1.Abci | ||
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): Class<out P8eContract> | ||
fun <T : P8eContract> setupContract(client: Client, contractClass: Class<T>, records: Map<String, Message>, scopeUuid: UUID, sessionUuid: UUID? = null): Session | ||
fun executeContract(client: Client, session: Session, executeTransaction: (SingleTx) -> Abci.TxResponse): Result<Abci.TxResponse> | ||
} |
8 changes: 8 additions & 0 deletions
8
service/src/main/kotlin/io/provenance/onboarding/domain/cee/InputParser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
2 changes: 1 addition & 1 deletion
2
...boarding/domain/provenance/ObjectStore.kt → ...oarding/domain/objectStore/ObjectStore.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 8 additions & 4 deletions
12
service/src/main/kotlin/io/provenance/onboarding/domain/provenance/Provenance.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,15 @@ | ||
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 java.util.UUID | ||
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 writeSpecifications(chainId: String, nodeEndpoint: String, account: Account, scopeId: UUID, contractSpecId: UUID, scopeSpecId: UUID, type: String) | ||
fun onboard(chainId: String, nodeEndpoint: String, account: Account, storeTxBody: TxBody): TxResponse | ||
fun executeTransaction(config: ProvenanceConfig, session: Session, tx: ProvenanceTx, signer: Signer): Abci.TxResponse | ||
} |
113 changes: 113 additions & 0 deletions
113
service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/ExecuteContract.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package io.provenance.onboarding.domain.usecase.cee | ||
|
||
import com.google.protobuf.Message | ||
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.scope.contract.annotations.Input | ||
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 io.provenance.scope.contract.spec.P8eContract | ||
import java.security.KeyPair | ||
import java.util.concurrent.TimeUnit | ||
import kotlin.reflect.full.functions | ||
import mu.KotlinLogging | ||
import org.springframework.stereotype.Component | ||
|
||
private val log = KotlinLogging.logger { } | ||
|
||
@Component | ||
class ExecuteContract( | ||
private val getOriginator: GetOriginator, | ||
private val contractService: ContractService, | ||
private val provenanceService: Provenance, | ||
private val getAccount: GetAccount, | ||
private val contractParser: ContractParser, | ||
) : AbstractUseCase<ExecuteContractRequest, TxResponse>() { | ||
|
||
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())), | ||
args.config.account.partyType, | ||
) | ||
|
||
val sharedClient = SharedClient( | ||
ClientConfig( | ||
mainNet = !args.config.account.isTestNet, | ||
cacheJarSizeInBytes = 4L * 1024 * 1024, // ~ 4 MB, | ||
cacheRecordSizeInBytes = 0L, | ||
cacheSpecSizeInBytes = 0L, | ||
disableContractLogs = !args.config.account.isTestNet, | ||
osConcurrencySize = 6, | ||
osGrpcUrl = URI(args.config.client.objectStoreUrl), | ||
osChannelCustomizeFn = { channelBuilder -> | ||
channelBuilder | ||
.idleTimeout(1, TimeUnit.MINUTES) | ||
.keepAliveTime(10, TimeUnit.SECONDS) | ||
.keepAliveTimeout(10, TimeUnit.SECONDS) | ||
} | ||
) | ||
) | ||
|
||
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.contract.scopeUuid, args.config.contract.sessionUuid) | ||
val signer = utils.getSigner(account) | ||
|
||
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<String, Any>, contract: Class<out P8eContract>): Map<String, Message> { | ||
val contractRecords = mutableMapOf<String, Message>() | ||
|
||
try { | ||
contract.kotlin.functions.forEach { func -> | ||
func.parameters.forEach { param -> | ||
(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 = contractParser.parseInput(recordToParse, parameterClass) | ||
contractRecords[input.name] = record | ||
} | ||
} | ||
} | ||
} catch (ex: Exception) { | ||
log.error("Failed to get inputs for contract ${contract.simpleName}") | ||
throw ex | ||
} | ||
|
||
return contractRecords | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ClientConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package io.provenance.onboarding.domain.usecase.cee.model | ||
|
||
data class ClientConfig( | ||
val objectStoreUrl: String, | ||
) |
9 changes: 9 additions & 0 deletions
9
service/src/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ContractConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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?, | ||
) |
11 changes: 11 additions & 0 deletions
11
...rc/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package io.provenance.onboarding.domain.usecase.cee.model | ||
|
||
import io.provenance.onboarding.domain.usecase.common.model.AccountInfo | ||
import io.provenance.onboarding.domain.usecase.common.model.ProvenanceConfig | ||
|
||
data class ExecuteContractConfig( | ||
val contract: ContractConfig, | ||
val client: ClientConfig, | ||
val account: AccountInfo, | ||
val provenanceConfig: ProvenanceConfig, | ||
) |
6 changes: 6 additions & 0 deletions
6
...c/main/kotlin/io/provenance/onboarding/domain/usecase/cee/model/ExecuteContractRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package io.provenance.onboarding.domain.usecase.cee.model | ||
|
||
data class ExecuteContractRequest( | ||
val config: ExecuteContractConfig, | ||
val records: Map<String, Any> | ||
) |
Oops, something went wrong.