-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bind chain contract invocations to specific VRF values (#6)
- Loading branch information
Showing
4 changed files
with
181 additions
and
151 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
30 changes: 16 additions & 14 deletions
30
src/main/scala/units/client/contract/ChainContractOptions.scala
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,32 +1,34 @@ | ||
package units.client.contract | ||
|
||
import com.wavesplatform.common.state.ByteStr | ||
import units.BlockHash | ||
import units.client.contract.ContractFunction.* | ||
import units.eth.{EthAddress, Gwei} | ||
|
||
/** @note | ||
* Make sure you have an activation gap: a new feature should not be activated suddenly during nearest blocks. | ||
*/ | ||
case class ChainContractOptions(miningReward: Gwei, elBridgeAddress: EthAddress) { | ||
def startEpochChainFunction(epochNumber: Int, chainInfo: Option[ChainInfo]): ContractFunction = { | ||
def startEpochChainFunction(reference: BlockHash, vrf: ByteStr, chainInfo: Option[ChainInfo]): ContractFunction = { | ||
chainInfo match { | ||
case Some(ci) => extendChainFunction(ci, epochNumber) | ||
case _ => startAltChainFunction(epochNumber) | ||
case Some(ci) => extendChainFunction(reference, vrf, ci) | ||
case _ => startAltChainFunction(reference, vrf) | ||
} | ||
} | ||
|
||
def appendFunction: ContractFunction = | ||
AppendBlock(V3) | ||
def appendFunction(reference: BlockHash): AppendBlock = | ||
AppendBlock(reference) | ||
|
||
private def extendChainFunction(chainInfo: ChainInfo, epochNumber: Int): ContractFunction = | ||
if (chainInfo.isMain) extendMainChainFunction(epochNumber) | ||
else extendAltChainFunction(chainInfo.id, epochNumber) | ||
private def extendChainFunction(reference: BlockHash, vrf: ByteStr, chainInfo: ChainInfo): ContractFunction = | ||
if (chainInfo.isMain) extendMainChainFunction(reference, vrf) | ||
else extendAltChainFunction(reference, vrf, chainInfo.id) | ||
|
||
private def extendMainChainFunction(epochNumber: Int): ContractFunction = | ||
ExtendMainChain(epochNumber, V3) | ||
private def extendMainChainFunction(reference: BlockHash, vrf: ByteStr): ContractFunction = | ||
ExtendMainChain(reference, vrf) | ||
|
||
private def extendAltChainFunction(chainId: Long, epochNumber: Int): ContractFunction = | ||
ExtendAltChain(chainId, epochNumber, V3) | ||
private def extendAltChainFunction(reference: BlockHash, vrf: ByteStr, chainId: Long): ContractFunction = | ||
ExtendAltChain(reference, vrf, chainId) | ||
|
||
private def startAltChainFunction(epochNumber: Int): ContractFunction = | ||
StartAltChain(epochNumber, V3) | ||
private def startAltChainFunction(reference: BlockHash, vrf: ByteStr): ContractFunction = | ||
StartAltChain(reference, vrf) | ||
} |
66 changes: 26 additions & 40 deletions
66
src/main/scala/units/client/contract/ContractFunction.scala
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,49 +1,35 @@ | ||
package units.client.contract | ||
|
||
import cats.syntax.option.* | ||
import units.client.contract.ContractFunction.* | ||
|
||
sealed abstract class ContractFunction( | ||
baseName: String, | ||
val chainIdOpt: Option[Long] = none, | ||
val epochOpt: Option[Int] = none | ||
) { | ||
def version: Version | ||
|
||
val name: String = s"$baseName${version.mineFunctionsSuffix}" | ||
import com.wavesplatform.common.merkle.Digest | ||
import com.wavesplatform.common.state.ByteStr | ||
import com.wavesplatform.lang.CommonError | ||
import com.wavesplatform.lang.v1.FunctionHeader | ||
import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BYTESTR, CONST_LONG, CONST_STRING, EVALUATED, FUNCTION_CALL} | ||
import units.{BlockHash, ClientError, Job} | ||
import units.util.HexBytesConverter.toHexNoPrefix | ||
import cats.syntax.either.* | ||
|
||
abstract class ContractFunction(name: String, reference: BlockHash, extraArgs: Either[CommonError, List[EVALUATED]]) { | ||
def toFunctionCall(blockHash: BlockHash, transfersRootHash: Digest, lastClToElTransferIndex: Long): Job[FUNCTION_CALL] = (for { | ||
hash <- CONST_STRING(blockHash) | ||
ref <- CONST_STRING(reference) | ||
trh <- CONST_STRING(toHexNoPrefix(transfersRootHash)) | ||
xtra <- extraArgs | ||
} yield FUNCTION_CALL( | ||
FunctionHeader.User(name), | ||
List(hash, ref) ++ xtra ++ List(trh, CONST_LONG(lastClToElTransferIndex)) | ||
)).leftMap(e => ClientError(s"Error building function call for $name: $e")) | ||
} | ||
|
||
object ContractFunction { | ||
val ExtendMainChainBaseName = "extendMainChain" | ||
val AppendBlockBaseName = "appendBlock" | ||
val ExtendAltChainBaseName = "extendAltChain" | ||
val StartAltChainBaseName = "startAltChain" | ||
|
||
case class ExtendMainChain(epoch: Int, version: Version) extends ContractFunction(ExtendMainChainBaseName, epochOpt = epoch.some) | ||
case class AppendBlock(version: Version) extends ContractFunction(AppendBlockBaseName) | ||
case class ExtendAltChain(chainId: Long, epoch: Int, version: Version) extends ContractFunction(ExtendAltChainBaseName, chainId.some, epoch.some) | ||
case class StartAltChain(epoch: Int, version: Version) extends ContractFunction(StartAltChainBaseName, epochOpt = epoch.some) | ||
|
||
val AllNames: List[String] = for { | ||
function <- List(ExtendMainChainBaseName, AppendBlockBaseName, ExtendAltChainBaseName, StartAltChainBaseName) | ||
version <- Version.All | ||
} yield function + version.mineFunctionsSuffix | ||
|
||
val StartAltChainNames = AllNames.filter(_.startsWith(StartAltChainBaseName)) | ||
case class ExtendMainChain(reference: BlockHash, vrf: ByteStr) | ||
extends ContractFunction("extendMainChain_v4", reference, CONST_BYTESTR(vrf).map(v => List(v))) | ||
|
||
sealed abstract class Version(protected val n: Int) extends Ordered[Version] with Product with Serializable { | ||
val mineFunctionsSuffix: String = s"_v$n" | ||
case class AppendBlock(reference: BlockHash) extends ContractFunction("appendBlock_v3", reference, Right(Nil)) | ||
|
||
override def compare(that: Version): Int = java.lang.Integer.compare(n, that.n) | ||
override def canEqual(that: Any): Boolean = that match { | ||
case _: Version => true | ||
case _ => false | ||
} | ||
} | ||
case class ExtendAltChain(reference: BlockHash, vrf: ByteStr, chainId: Long) | ||
extends ContractFunction("extendAltChain_v4", reference, CONST_BYTESTR(vrf).map(v => List(v, CONST_LONG(chainId)))) | ||
|
||
case object V2 extends Version(2) // Supports EL to CL transfers | ||
case object V3 extends Version(3) // Supports CL to EL transfers | ||
object Version { | ||
val All = List(V2, V3) | ||
} | ||
case class StartAltChain(reference: BlockHash, vrf: ByteStr) | ||
extends ContractFunction("startAltChain_v4", reference, CONST_BYTESTR(vrf).map(v => List(v))) | ||
} |
Oops, something went wrong.