-
-
Save birchmd/f25578323b249ae03a45499a8165ab9d to your computer and use it in GitHub Desktop.
Scala code making use of rchain project resources to generate Rholang that performs transfers
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
import coop.rchain.casper.genesis.contracts.{Rev, Wallet} | |
import coop.rchain.casper.util.rholang.InterpreterUtil.mkTerm | |
import coop.rchain.casper.util.rholang.RuntimeManager | |
import coop.rchain.crypto.codec.Base16 | |
import coop.rchain.crypto.hash.Blake2b256 | |
import coop.rchain.crypto.signatures.Ed25519 | |
import coop.rchain.rholang.interpreter.Runtime | |
import coop.rchain.shared.PathOps.RichPath | |
import java.io.PrintWriter | |
import java.nio.file.Files | |
import monix.execution.Scheduler.Implicits.global | |
import Wallet._ | |
object RChainWalletTransfers { | |
//give a simple address for a wallet | |
def depositAddress(wallet: Wallet): String = "0x" + rhoPublicName(wallet).split(':').last.dropRight(1) | |
//generate the rholang code for accepting purses at an address | |
def depositForwarder(wallet: Wallet): String = { | |
val address = depositAddress(wallet) | |
s""" | |
contract @"$address"(@purse) = { | |
new purseAmountCh, return(`rho:io:stdout`) in { | |
@(purse, "getBalance")!(*purseAmountCh) | | |
for(@wallet <- ${rhoPublicName(wallet)}; @amount <- purseAmountCh) { | |
@(wallet, "deposit")!(amount, purse, *return) | |
} | |
} | |
} | |
""" | |
} | |
//generate rholang code for transferring rev between wallets | |
def transfer(from: Wallet, to: Wallet, amount: Int, nonce: Int, sk: Array[Byte])(implicit rm: RuntimeManager): String = { | |
val destName = depositAddress(to) | |
val sigData = rm.captureResults(rm.emptyStateHash, mkTerm(s""" @"__SCALA__"!([$nonce, $amount, "$destName"].toByteArray()) """).right.get).head.exprs.head.getGByteArray | |
val sig = Base16.encode(Ed25519.sign(Blake2b256.hash(sigData.toByteArray), sk)) | |
s""" | |
for(@wallet <- ${rhoPublicName(from)}) { | |
new status(`rho:io:stdout`) in { | |
@(wallet, "transfer")!($amount, $nonce, "$sig", "$destName", *status) | |
} | |
} | |
""" | |
} | |
def writeToFile(code: String, name: String): Unit = { | |
val out = new PrintWriter(s"./$name.rho") | |
out.println(code) | |
out.close() | |
} | |
def main(args: Array[String]): Unit = { | |
//main method to actually generate the rholang code | |
val runtimeDir = Files.createTempDirectory("casper-rholang-interpreter-") | |
val runtime = Runtime.create(runtimeDir, 1024L * 1024 * 10) | |
implicit val runtimeManager = RuntimeManager.fromRuntime(runtime) | |
val n: Int = args.head.toInt //number of wallets to make | |
val (sks, pks) = (1 to n).map(_ => Ed25519.newKeyPair).unzip | |
val wallets = pks.map(pk => Wallet("ed25519", Base16.encode(pk), 100)) | |
val rev = new Rev[Wallet](Wallet.rhoCode, wallets) | |
val depositForwarders = wallets.map(depositForwarder) | |
val transfers = { //set up transfers between wallets; could be modified to do more txns | |
val wsks = wallets.zip(sks) | |
wsks.zip(wallets.tail).map { | |
case ((from, sk), to) => transfer(from, to, 11, 0, sk) | |
} | |
} | |
//Note that this generated code assumes NonNegativeNumber.rho, MakeMint.rho and BasicWallet.rho | |
//are already deployed. This is is the case for node instances because those contracts are in | |
//the genesis block. | |
val walletSeupCode = (rev.code +: depositForwarders).mkString(" |\n") | |
val transferCode = transfers.mkString(" |\n") | |
writeToFile(walletSeupCode, "walletSeup") | |
writeToFile(transferCode, "transfers") | |
runtime.close() | |
runtimeDir.recursivelyDelete() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment