Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add base support of polkadot/substrate/vara chain #332

Merged
merged 4 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions buildSrc/src/main/kotlin/chainsconfig.codegen.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.ChainsConfigReader
import io.emeraldpay.dshackle.foundation.ChainOptionsReader
Expand All @@ -18,7 +19,7 @@ open class CodeGen(private val config: ChainsConfig) {
builder.addEnumConstant(
"UNSPECIFIED",
TypeSpec.anonymousClassBuilder()
.addSuperclassConstructorParameter("%L, %S, %S, %S, %L, %L", 0, "UNSPECIFIED", "Unknown", "0x0", "BigInteger.ZERO", "emptyList()")
.addSuperclassConstructorParameter("%L, %S, %S, %S, %L, %L, %L", 0, "UNSPECIFIED", "Unknown", "0x0", "BigInteger.ZERO", "emptyList()", "BlockchainType.UNKNOWN")
.build(),
)
for (chain in config) {
Expand All @@ -27,13 +28,14 @@ open class CodeGen(private val config: ChainsConfig) {
.replace(' ', '_'),
TypeSpec.anonymousClassBuilder()
.addSuperclassConstructorParameter(
"%L, %S, %S, %S, %L, %L",
"%L, %S, %S, %S, %L, %L, %L",
chain.grpcId,
chain.code,
chain.blockchain.replaceFirstChar { it.uppercase() } + " " + chain.id.replaceFirstChar { it.uppercase() },
chain.chainId,
"BigInteger(\"" + chain.netVersion + "\")",
"listOf(" + chain.shortNames.map { "\"${it}\"" }.joinToString() + ")",
type(chain.type)
)
.build(),
)
Expand Down Expand Up @@ -65,6 +67,7 @@ open class CodeGen(private val config: ChainsConfig) {
.addParameter("chainId", String::class)
.addParameter("netVersion", BigInteger::class)
.addParameter("shortNames", List::class.asClassName().parameterizedBy(String::class.asClassName()))
.addParameter("type", BlockchainType::class)
.build(),
)
.addProperty(
Expand Down Expand Up @@ -96,12 +99,27 @@ open class CodeGen(private val config: ChainsConfig) {
PropertySpec.builder("shortNames", List::class.asClassName().parameterizedBy(String::class.asClassName()))
.initializer("shortNames")
.build(),
),
)
.addProperty(
PropertySpec.builder("type", BlockchainType::class)
.initializer("type")
.build(),
)
).build()
return FileSpec.builder("io.emeraldpay.dshackle", "Chain")
.addType(chainType)
.build()
}

private fun type(type: String): String {
return when(type) {
"eth" -> "BlockchainType.ETHEREUM"
"bitcoin" -> "BlockchainType.BITCOIN"
"starknet" -> "BlockchainType.STARKNET"
"polkadot" -> "BlockchainType.POLKADOT"
else -> throw IllegalArgumentException("unknown blockchain type $type")
}
}
}

open class ChainsCodeGenTask : DefaultTask() {
Expand Down
2 changes: 1 addition & 1 deletion emerald-grpc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.emeraldpay.dshackle

enum class BlockchainType {
UNKNOWN, BITCOIN, ETHEREUM, STARKNET, POLKADOT;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ data class ChainsConfig(private val chains: List<ChainConfig>) : Iterable<Chains
val callLimitContract: String?,
val id: String,
val blockchain: String,
val type: String
) {
companion object {
@JvmStatic
Expand All @@ -49,6 +50,7 @@ data class ChainsConfig(private val chains: List<ChainConfig>) : Iterable<Chains
callLimitContract,
"undefined",
"undefined",
"unknown"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class ChainsConfigReader(
protocols.value.fold(emptyMap()) { acc, protocol ->
val blockchain = getValueAsString(protocol, "id")
?: throw IllegalArgumentException("Blockchain id is not defined")
val type = getValueAsString(protocol, "type")
?: throw IllegalArgumentException("undefined type for $blockchain")
val settings = mergeMappingNode(default, getMapping(protocol, "settings"))
acc.plus(
getList<MappingNode>(protocol, "chains")?.let { chains ->
Expand All @@ -38,6 +40,10 @@ class ChainsConfigReader(
ScalarNode(Tag.STR, "blockchain", null, null, DumperOptions.ScalarStyle.LITERAL),
ScalarNode(Tag.STR, blockchain, null, null, DumperOptions.ScalarStyle.LITERAL),
),
NodeTuple(
ScalarNode(Tag.STR, "type", null, null, DumperOptions.ScalarStyle.LITERAL),
ScalarNode(Tag.STR, type, null, null, DumperOptions.ScalarStyle.LITERAL),
),
),
chain.flowStyle,
),
Expand Down Expand Up @@ -78,6 +84,8 @@ class ChainsConfigReader(
val netVersion = getValueAsLong(node, "net-version")?.toBigInteger() ?: BigInteger(chainId.drop(2), 16)
val shortNames = getListOfString(node, "short-names")
?: throw IllegalArgumentException("undefined shortnames for $blockchain")
val type = getValueAsString(node, "type")
?: throw IllegalArgumentException("undefined type for $blockchain")
return ChainsConfig.ChainConfig(
expectedBlockTime = expectedBlockTime,
syncingLagSize = lags.first,
Expand All @@ -91,6 +99,7 @@ class ChainsConfigReader(
shortNames = shortNames,
id = id,
blockchain = blockchain,
type = type
)
}

Expand Down
23 changes: 23 additions & 0 deletions foundation/src/main/resources/chains.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -641,3 +641,26 @@ chain-settings:
short-names: [ astar-zkatana ]
chain-id: 0x133e40
grpcId: 10035
- id: vara
label: varanet
type: polkadot
settings:
expected-block-time: 3s
options:
validate-peers: false
lags:
syncing: 10
lagging: 5
chains:
- id: Mainnet
priority: 1
code: VARA_MAINNET
short-names: [ vara ]
chain-id: 0x0
grpcId: 1027
- id: Testnet
priority: 1
code: VARA_TESTMET
short-names: [ vara-testnet ]
chain-id: 0x0
grpcId: 10036
1 change: 1 addition & 0 deletions foundation/src/test/resources/configs/chains-basic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ version: v1
chain-settings:
protocols:
- id: fantom
type: eth
settings:
expected-block-time: 10s
options:
Expand Down
22 changes: 0 additions & 22 deletions src/main/kotlin/io/emeraldpay/dshackle/BlockchainType.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class TokensConfig(
type == null -> type
address.isNullOrBlank() -> "address"
blockchain != null &&
(BlockchainType.from(blockchain!!) == BlockchainType.ETHEREUM) &&
(blockchain!!.type == BlockchainType.ETHEREUM) &&
!Address.isValidAddress(address) -> "address"
else -> null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.emeraldpay.dshackle.config.context

import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.BlockchainType.BITCOIN
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.CachesFactory
Expand Down Expand Up @@ -30,7 +29,7 @@ open class MultistreamsConfig(val beanFactory: ConfigurableListableBeanFactory)
return Chain.entries
.filterNot { it == Chain.UNSPECIFIED }
.map { chain ->
if (BlockchainType.from(chain) == BITCOIN) {
if (chain.type == BITCOIN) {
bitcoinMultistream(chain, cachesFactory, headScheduler)
} else {
genericMultistream(chain, cachesFactory, headScheduler, tracer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,10 @@ class AccessHandlerGrpc(
): ServerCall.Listener<ReqT> {
return when (val method = call.methodDescriptor.bareMethodName) {
"SubscribeHead" -> processSubscribeHead(call, headers, next)
"SubscribeBalance" -> processSubscribeBalance(call, headers, next, true)
"SubscribeTxStatus" -> processSubscribeTxStatus(call, headers, next)
"GetBalance" -> processSubscribeBalance(call, headers, next, false)
"NativeCall" -> processNativeCall(call, headers, next)
"NativeSubscribe" -> processNativeSubscribe(call, headers, next)
"Describe" -> processDescribe(call, headers, next)
"SubscribeStatus" -> processStatus(call, headers, next)
"EstimateFee" -> processEstimateFee(call, headers, next)
else -> {
log.warn("unsupported method `{}`", method)
next.startCall(call, headers)
Expand Down Expand Up @@ -90,35 +86,6 @@ class AccessHandlerGrpc(
)
}

@Suppress("UNCHECKED_CAST")
private fun <ReqT : Any, RespT : Any> processSubscribeBalance(
call: ServerCall<ReqT, RespT>,
headers: Metadata,
next: ServerCallHandler<ReqT, RespT>,
subscribe: Boolean,
): ServerCall.Listener<ReqT> {
return process(
call,
headers,
next,
EventsBuilder.SubscribeBalance(subscribe) as EventsBuilder.RequestReply<*, ReqT, RespT>,
)
}

@Suppress("UNCHECKED_CAST")
private fun <ReqT : Any, RespT : Any> processSubscribeTxStatus(
call: ServerCall<ReqT, RespT>,
headers: Metadata,
next: ServerCallHandler<ReqT, RespT>,
): ServerCall.Listener<ReqT> {
return process(
call,
headers,
next,
EventsBuilder.TxStatus() as EventsBuilder.RequestReply<*, ReqT, RespT>,
)
}

@Suppress("UNCHECKED_CAST")
private fun <ReqT : Any, RespT : Any> processNativeCall(
call: ServerCall<ReqT, RespT>,
Expand Down Expand Up @@ -175,20 +142,6 @@ class AccessHandlerGrpc(
)
}

@Suppress("UNCHECKED_CAST")
private fun <ReqT : Any, RespT : Any> processEstimateFee(
call: ServerCall<ReqT, RespT>,
headers: Metadata,
next: ServerCallHandler<ReqT, RespT>,
): ServerCall.Listener<ReqT> {
return process(
call,
headers,
next,
EventsBuilder.EstimateFee() as EventsBuilder.RequestReply<*, ReqT, RespT>,
)
}

open class StdCallListener<Req, EB : EventsBuilder.RequestReply<*, Req, *>>(
val next: ServerCall.Listener<Req>,
val builder: EB,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import java.net.InetAddress
import java.net.InetSocketAddress
import java.time.Duration
import java.time.Instant
import java.util.Locale
import java.util.UUID

class EventsBuilder {
Expand Down Expand Up @@ -244,69 +243,6 @@ class EventsBuilder {
}
}

class SubscribeBalance(val subscribe: Boolean) :
Base<SubscribeBalance>(),
RequestReply<Events.SubscribeBalance, BlockchainOuterClass.BalanceRequest, BlockchainOuterClass.AddressBalance> {

private var index = 0
private var balanceRequest: Events.BalanceRequest? = null

override fun getT(): SubscribeBalance {
return this
}

override fun onRequest(msg: BlockchainOuterClass.BalanceRequest) {
balanceRequest = Events.BalanceRequest(
msg.asset.code.uppercase(Locale.getDefault()),
msg.address.addrTypeCase.name,
)
}

override fun onReply(msg: BlockchainOuterClass.AddressBalance): Events.SubscribeBalance {
if (balanceRequest == null) {
throw IllegalStateException("Request is not initialized")
}
val addressBalance = Events.AddressBalance(msg.asset.code, msg.address.address)
val chain = Chain.byId(msg.asset.chain.number)
return Events.SubscribeBalance(
chain,
UUID.randomUUID(),
subscribe,
requestDetails,
balanceRequest!!,
addressBalance,
index++,
)
}
}

class TxStatus :
Base<TxStatus>(),
RequestReply<Events.TxStatus, BlockchainOuterClass.TxStatusRequest, BlockchainOuterClass.TxStatus> {
private var index = 0
private var txStatusRequest: Events.TxStatusRequest? = null

override fun onRequest(msg: BlockchainOuterClass.TxStatusRequest) {
this.txStatusRequest = Events.TxStatusRequest(msg.txId)
withChain(msg.chainValue)
}

override fun onReply(msg: BlockchainOuterClass.TxStatus): Events.TxStatus {
return Events.TxStatus(
chain,
UUID.randomUUID(),
requestDetails,
txStatusRequest!!,
Events.TxStatusResponse(msg.confirmations),
index++,
)
}

override fun getT(): TxStatus {
return this
}
}

class NativeCall(private val startTs: Instant) :
Base<NativeCall>(),
RequestReply<Events.NativeCall, BlockchainOuterClass.NativeCallRequest, BlockchainOuterClass.NativeCallReplyItem> {
Expand Down Expand Up @@ -496,34 +432,4 @@ class EventsBuilder {
)
}
}

class EstimateFee :
Base<EstimateFee>(),
RequestReply<Events.EstimateFee, BlockchainOuterClass.EstimateFeeRequest, BlockchainOuterClass.EstimateFeeResponse> {

private var mode: String = "UNKNOWN"
private var blocks: Int = 0

override fun getT(): EstimateFee {
return this
}

override fun onRequest(msg: BlockchainOuterClass.EstimateFeeRequest) {
this.chain = Chain.byId(msg.chain.number)
this.mode = msg.mode.name
this.blocks = msg.blocks
}

override fun onReply(msg: BlockchainOuterClass.EstimateFeeResponse): Events.EstimateFee {
return Events.EstimateFee(
blockchain = chain,
request = requestDetails,
id = UUID.randomUUID(),
estimateFee = Events.EstimateFeeDetails(
mode = mode,
blocks = blocks,
),
)
}
}
}
Loading
Loading