Skip to content

Commit

Permalink
Merge pull request #73 from virtualeconomy/Contract
Browse files Browse the repository at this point in the history
Basic Contract and Token Related Contract
  • Loading branch information
ncying authored May 14, 2019
2 parents dbd594b + 112c8ed commit 62d1093
Show file tree
Hide file tree
Showing 106 changed files with 5,399 additions and 759 deletions.
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,8 @@ native
.DS_Store
minter_target

test
test/*
/test
/test/*

test/data/*
test/*/data/*
7 changes: 4 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ enablePlugins(sbtdocker.DockerPlugin, JavaServerAppPackaging, JDebPackaging, Sys

name := "vsys"
organization := "systems.v"
version := "0.1.1"
version := "0.2.0"
scalaVersion in ThisBuild := "2.12.6"
crossPaths := false
publishArtifact in (Compile, packageDoc) := false
Expand Down Expand Up @@ -47,12 +47,13 @@ libraryDependencies ++=
("org.scorexfoundation" %% "scrypto" % "1.2.2")
.exclude("org.slf4j", "slf4j-api"),
"commons-net" % "commons-net" % "3.+",
"org.typelevel" %% "cats-core" % "0.9.0",
"org.typelevel" %% "cats-core" % "1.0.0-RC1",
"io.monix" %% "monix" % "3.0.0-M2"
)

dependencyOverrides ++= Seq(
"com.google.guava" % "guava" % "21.0"
"com.google.guava" % "guava" % "21.0",
"com.typesafe.akka" % "akka-actor_2.12" % "2.5.14"
)

sourceGenerators in Compile += Def.task {
Expand Down
6 changes: 3 additions & 3 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import sbt._

object Dependencies {

def akkaModule(module: String) = "com.typesafe.akka" %% s"akka-$module" % "2.4.19"
def akkaModule(module: String) = "com.typesafe.akka" %% s"akka-$module" % "2.5.14"
def swaggerModule(module: String) = ("io.swagger" % s"swagger-$module" % "1.5.22").exclude("com.google.guava", "guava")
def akkaHttpModule(module: String) = "com.typesafe.akka" %% module % "10.0.9"
def akkaHttpModule(module: String) = "com.typesafe.akka" %% module % "10.1.3"
def nettyModule(module: String) = "io.netty" % s"netty-$module" % "4.1.24.Final"
def kamonModule(module: String) = "io.kamon" %% s"kamon-$module" % "0.6.7"

Expand Down Expand Up @@ -53,7 +53,7 @@ object Dependencies {
)

lazy val http = Seq("core", "annotations", "models", "jaxrs").map(swaggerModule) ++ Seq(
"io.swagger" %% "swagger-scala-module" % "1.0.4",
"io.swagger" %% "swagger-scala-module" % "1.0.5",
"com.github.swagger-akka-http" %% "swagger-akka-http" % "1.0.0",
akkaHttpModule("akka-http")
)
Expand Down
13 changes: 5 additions & 8 deletions src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
vsys {
# Node base directory
directory = ${user.home}"/.vsys"
data-directory = ${user.home}"/.vsys/data"
data-directory = ${vsys.directory}"/data"

# Application logging level. Could be TRACE | DEBUG | INFO | WARN | ERROR. Default value is INFO.
logging-level = INFO
Expand Down Expand Up @@ -205,14 +205,11 @@ vsys {
release-slots {
VSYS = 10000000
}
minting {
VSYS = 100000
register-contract {
VSYS = 10000000000
}
create-contract {
VSYS = 20000000
}
change-contract-status {
VSYS = 10000000
execute-contract-function {
VSYS = 30000000
}
db-put {
VSYS = 100000000
Expand Down
9 changes: 5 additions & 4 deletions src/main/scala/com/wavesplatform/Application.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import kamon.Kamon
import scorex.account.AddressScheme
import scorex.api.http._
import vsys.api.http.spos.{SPOSApiRoute, SPOSBroadcastApiRoute}
import vsys.api.http.contract.{ContractApiRoute, ContractBroadcastApiRoute}
import vsys.api.http.vsys._
import vsys.api.http.database.DbApiRoute
import scorex.api.http.leasing.{LeaseApiRoute, LeaseBroadcastApiRoute}
Expand Down Expand Up @@ -106,8 +107,8 @@ class Application(val actorSystem: ActorSystem, val settings: VsysSettings) exte
//AliasBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels),
SPOSApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader),
SPOSBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels),
//ContractApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader),
//ContractBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels),
ContractApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader),
ContractBroadcastApiRoute(settings.restAPISettings, utxStorage, allChannels),
DbApiRoute(settings.restAPISettings, wallet, utxStorage, allChannels, time, stateReader)
)

Expand All @@ -131,8 +132,8 @@ class Application(val actorSystem: ActorSystem, val settings: VsysSettings) exte
//classOf[AliasBroadcastApiRoute],
classOf[SPOSApiRoute],
classOf[SPOSBroadcastApiRoute],
//classOf[ContractApiRoute],
//classOf[ContractBroadcastApiRoute],
classOf[ContractApiRoute],
classOf[ContractBroadcastApiRoute],
classOf[DbApiRoute]
)

Expand Down
13 changes: 10 additions & 3 deletions src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,23 @@ import net.ceedubs.ficus.readers.EnumerationReader._
import vsys.settings._

case class FunctionalitySettings(numOfSlots: Int,
mintingSpeed: Int)
mintingSpeed: Int,
allowContractTransactionAfterHeight: Int)

object FunctionalitySettings {
val MAINNET = FunctionalitySettings(
numOfSlots = 60,
mintingSpeed = 1)
mintingSpeed = 1,
//TODO
//set the value
allowContractTransactionAfterHeight = Int.MaxValue)

val TESTNET = FunctionalitySettings(
numOfSlots = 60,
mintingSpeed = 1)
mintingSpeed = 1,
//TODO
//set the value
allowContractTransactionAfterHeight = 423600)

val configPath = "vsys.blockchain.custom.functionality"
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/scala/com/wavesplatform/state2/DataTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,32 @@ object DataTypes {
buff.put(v)
}
}

// (Int, ByteStr, Array[Byte])
val contracts: DataType = new DTTemplate {
override def compare(a: scala.Any, b: scala.Any) = throw new UnsupportedOperationException

override def read(buff: ByteBuffer): AnyRef = {
val i = readVarInt(buff)
val dst = new Array[Byte](readVarInt(buff))
buff.get(dst)
val b = new Array[Byte](readVarInt(buff))
buff.get(b)
(i, ByteStr(dst), b)
}

override def getMemory(obj: scala.Any) = {
val (_, bstr, ba) = obj.asInstanceOf[(Int, ByteStr, Array[Byte])]
10 + bstr.arr.length + 5 + ba.length
}

override def write(buff: WriteBuffer, obj: scala.Any) = {
val (i, bstr, ba) = obj.asInstanceOf[(Int, ByteStr, Array[Byte])]
buff.putVarInt(i)
.putVarInt(bstr.arr.length)
.put(bstr.arr)
.putVarInt(ba.length)
.put(ba)
}
}
}
39 changes: 35 additions & 4 deletions src/main/scala/com/wavesplatform/state2/Diff.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import cats.implicits._
import scorex.account.{Address, Alias}
import vsys.database.Entry
import scorex.transaction.Transaction
import vsys.contract.Contract
import vsys.transaction.{ProcessedTransaction, TransactionStatus}

case class Snapshot(prevHeight: Int, balance: Long, effectiveBalance: Long, weightedBalance: Long)
Expand Down Expand Up @@ -50,7 +51,11 @@ case class Diff(transactions: Map[ByteStr, (Int, ProcessedTransaction, Set[Addre
slotNum: Int,
txStatus: TransactionStatus.Value,
chargedFee: Long,
contracts: Map[String, (Boolean, Address, String)],
contracts: Map[ByteStr, (Int, ByteStr, Contract, Set[Address])],
contractDB: Map[ByteStr, Array[Byte]],
contractTokens: Map[ByteStr, Int],
tokenDB: Map[ByteStr, Array[Byte]],
tokenAccountBalance: Map[ByteStr, Long],
dbEntries: Map[ByteStr, Entry],
orderFills: Map[ByteStr, OrderFillInfo],
leaseState: Map[ByteStr, Boolean]) {
Expand All @@ -65,6 +70,17 @@ case class Diff(transactions: Map[ByteStr, (Int, ProcessedTransaction, Set[Addre
.mapValues(l => l.toList.sortBy { case ((h, t, _)) => (-h, -t) }) // fresh head ([h=2, h=1, h=0])
.mapValues(_.map(_._3))
}

lazy val accountContractIds: Map[Address, List[ByteStr]] = {
val map: List[(Address, Set[(Int, ByteStr)])] = contracts.toList
.flatMap { case (id, (h, _, _, accs)) => accs.map(acc => acc -> Set((h, id))) }
val groupedByAcc = map.foldLeft(Map.empty[Address, Set[(Int, ByteStr)]]) { case (m, (acc, set)) =>
m.combine(Map(acc -> set))
}
groupedByAcc
.mapValues(l => l.toList.sortBy { case ((h, _)) => (-h) }) // fresh head ([h=2, h=1, h=0])
.mapValues(_.map(_._2))
}
}

object Diff {
Expand All @@ -77,11 +93,16 @@ object Diff {
slotNum: Int = 0,
txStatus: TransactionStatus.Value = TransactionStatus.Success,
chargedFee: Long = 0,
contracts: Map[String, (Boolean, Address, String)] = Map.empty,
contracts: Map[ByteStr, (Int, ByteStr, Contract, Set[Address])] = Map.empty,
contractDB: Map[ByteStr, Array[Byte]] = Map.empty,
contractTokens: Map[ByteStr, Int] = Map.empty,
tokenDB: Map[ByteStr, Array[Byte]] = Map.empty,
tokenAccountBalance: Map[ByteStr, Long] = Map.empty,
relatedAddress: Map[Address, Boolean] = Map.empty,
dbEntries: Map[ByteStr, Entry] = Map.empty,
orderFills: Map[ByteStr, OrderFillInfo] = Map.empty,
leaseState: Map[ByteStr, Boolean] = Map.empty): Diff = Diff(
transactions = Map((tx.id, (height, ProcessedTransaction(txStatus, chargedFee, tx), portfolios.keys.toSet))),
transactions = Map((tx.id, (height, ProcessedTransaction(txStatus, chargedFee, tx), (portfolios.keys ++ relatedAddress.keys).toSet))),
portfolios = portfolios,
issuedAssets = assetInfos,
aliases = aliases,
Expand All @@ -91,11 +112,17 @@ object Diff {
txStatus = txStatus,
chargedFee = chargedFee,
contracts = contracts,
contractDB = contractDB,
contractTokens = contractTokens,
tokenDB = tokenDB,
tokenAccountBalance = tokenAccountBalance,
dbEntries = dbEntries,
orderFills = orderFills,
leaseState = leaseState)

val empty = new Diff(Map.empty, Map.empty, Map.empty, Map.empty, Map.empty, Map.empty, 0, TransactionStatus.Unprocessed, 0L, Map.empty, Map.empty, Map.empty, Map.empty)
val empty = new Diff(Map.empty, Map.empty, Map.empty, Map.empty, Map.empty, Map.empty, 0,
TransactionStatus.Unprocessed, 0L, Map.empty, Map.empty,
Map.empty, Map.empty, Map.empty, Map.empty, Map.empty, Map.empty)

implicit class DiffExt(d: Diff) {
def asBlockDiff: BlockDiff = BlockDiff(d, 0, Map.empty)
Expand All @@ -115,6 +142,10 @@ object Diff {
txStatus = newer.txStatus,
chargedFee = newer.chargedFee,
contracts = older.contracts ++ newer.contracts,
contractDB = older.contractDB ++ newer.contractDB,
contractTokens = Monoid.combine(older.contractTokens, newer.contractTokens),
tokenDB = older.tokenDB ++ newer.tokenDB,
tokenAccountBalance = Monoid.combine(older.tokenAccountBalance, newer.tokenAccountBalance),
dbEntries = older.dbEntries ++ newer.dbEntries,
orderFills = older.orderFills.combine(newer.orderFills),
leaseState = older.leaseState ++ newer.leaseState)
Expand Down
14 changes: 13 additions & 1 deletion src/main/scala/com/wavesplatform/state2/StateStorage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,19 @@ class StateStorage private(db: DB) extends Storage(db){

val lastBalanceSnapshotWeightedBalance: StateMap[ByteStr, Long] = new StateMap(db, "lastUpdateWeightedBalance", keyType=DataTypes.byteStr)

val contracts: StateMap[String, (Boolean, ByteStr, String)] = new StateMap(db, "contracts")
val contracts: StateMap[ByteStr, (Int, ByteStr, Array[Byte])] = new StateMap(db, "contracts", keyType=DataTypes.byteStr, valueType=DataTypes.contracts)

val accountContractIds: StateMap[AccountIdxKey, ByteStr] = new StateMap(db, "accountContractIds", valueType=DataTypes.byteStr)

val accountContractsLengths: StateMap[ByteStr, Int] = new StateMap(db, "accountContractsLengths", keyType=DataTypes.byteStr)

val contractDB: StateMap[ByteStr, Array[Byte]] = new StateMap(db, "contractDB", keyType=DataTypes.byteStr)

val contractTokens: StateMap[ByteStr, Int] = new StateMap(db, "contractTokens", keyType=DataTypes.byteStr)

val tokenDB: StateMap[ByteStr, Array[Byte]] = new StateMap(db, "tokenDB", keyType=DataTypes.byteStr)

val tokenAccountBalance: StateMap[ByteStr, Long] = new StateMap(db, "tokenAccountBalance", keyType=DataTypes.byteStr)

// only support Entry.bytes, in case later we want to support different types and not sure how to serialize here?
val dbEntries: StateMap[ByteStr, ByteStr] = new StateMap(db, "dbEntries", keyType=DataTypes.byteStr, valueType=DataTypes.byteStr)
Expand Down
42 changes: 40 additions & 2 deletions src/main/scala/com/wavesplatform/state2/StateWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import scorex.utils.ScorexLogging

import scala.language.higherKinds


trait StateWriter {
def applyBlockDiff(blockDiff: BlockDiff): Unit

Expand Down Expand Up @@ -93,8 +94,45 @@ class StateWriterImpl(p: StateStorage, synchronizationToken: ReentrantReadWriteL
}

measureSizeLog("contracts")(blockDiff.txsDiff.contracts) {
_.foreach { case (name, (status, account, content)) =>
sp().contracts.put(name, (status, account.bytes, content))
_.foreach { case (id, (h, txId, contract, _)) =>
sp().contracts.put(id, (h, txId, contract.bytes.arr))
}
}

measureSizeLog("accountContractIds")(blockDiff.txsDiff.accountContractIds) {
_.foreach { case (acc, ctIds) =>
val startIdxShift = sp().accountContractsLengths.get(acc.bytes).getOrElse(0)
ctIds.reverse.foldLeft(startIdxShift) { case (shift, ctId) =>
sp().accountContractIds.put(accountIndexKey(acc, shift), ctId)
shift + 1
}
sp().accountContractsLengths.put(acc.bytes, startIdxShift + ctIds.length)
}
}

measureSizeLog("contractDB")(blockDiff.txsDiff.contractDB) {
_.foreach { case (id, contractData) =>
sp().contractDB.put(id, contractData)
}
}

measureSizeLog("contractTokens")(blockDiff.txsDiff.contractTokens) {
_.foreach { case (id, tokenNum) =>
val updatedNum = contractTokens(id) + tokenNum
sp().contractTokens.put(id, updatedNum)
}
}

measureSizeLog("tokenDB")(blockDiff.txsDiff.tokenDB) {
_.foreach { case (id, tokeninfo) =>
sp().tokenDB.put(id, tokeninfo)
}
}

measureSizeLog("tokenAccountBalance")(blockDiff.txsDiff.tokenAccountBalance) {
_.foreach { case (id, balance) =>
val updatedBalance = safeSum(tokenAccountBalance(id), balance)
sp().tokenAccountBalance.put(id, updatedBalance)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ import com.wavesplatform.state2.{Portfolio, _}
import scorex.account.Address
import scorex.transaction.ValidationError.{GenericError, Mistiming}
import scorex.transaction._
import scorex.transaction.lease._
import scorex.transaction.assets._
import vsys.transaction.proof.EllipticCurve25519Proof
import vsys.transaction.contract._
import vsys.transaction.spos._
import vsys.transaction.database._
import vsys.transaction._

import scala.concurrent.duration._
import scala.util.{Left, Right}
Expand Down Expand Up @@ -58,6 +63,25 @@ object CommonValidation {
else Right(tx)
}

def disallowBeforeActivationHeight[T <: Transaction](settings: FunctionalitySettings, h: Int, tx: T): Either[ValidationError, T] =
tx match {
case tx: RegisterContractTransaction if h <= settings.allowContractTransactionAfterHeight =>
Left(GenericError(s"must not appear before height=${settings.allowContractTransactionAfterHeight}"))
case tx: ExecuteContractFunctionTransaction if h <= settings.allowContractTransactionAfterHeight =>
Left(GenericError(s"must not appear before time=${settings.allowContractTransactionAfterHeight}"))
case _: GenesisTransaction => Right(tx)
case _: PaymentTransaction => Right(tx)
case _: LeaseTransaction => Right(tx)
case _: LeaseCancelTransaction => Right(tx)
case _: MintingTransaction => Right(tx)
case _: ContendSlotsTransaction => Right(tx)
case _: ReleaseSlotsTransaction => Right(tx)
case _: RegisterContractTransaction => Right(tx)
case _: ExecuteContractFunctionTransaction => Right(tx)
case _: DbPutTransaction => Right(tx)
case _ => Left(GenericError("Unknown transaction must be explicitly registered within ActivatedValidator"))
}

def disallowTxFromFuture[T <: Transaction](time: Long, tx: T): Either[ValidationError, T] = {

if ((tx.timestamp - time) > MaxTimeTransactionOverBlockDiff.toNanos)
Expand Down
Loading

0 comments on commit 62d1093

Please sign in to comment.