scodec.bits.ByteVector Scala Examples
The following examples show how to use scodec.bits.ByteVector.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: ByteVectorBytes.scala From swave with Mozilla Public License 2.0 | 5 votes |
package swave.compat.scodec.impl import java.io.OutputStream import java.nio.ByteBuffer import java.nio.charset.{CharacterCodingException, Charset} import scala.collection.GenTraversableOnce import scodec.bits.ByteVector import swave.core.io.Bytes class ByteVectorBytes extends Bytes[ByteVector] { ///////////////// CONSTRUCTION /////////////////// def empty = ByteVector.empty def fill[A: Integral](size: Long)(byte: A) = ByteVector.fill(size)(byte) def apply(array: Array[Byte]) = ByteVector(array) def apply(bytes: Array[Byte], offset: Int, length: Int) = ByteVector(bytes, offset, length) def apply[A: Integral](bytes: A*) = ByteVector(bytes: _*) def apply(bytes: Vector[Byte]) = ByteVector(bytes) def apply(buffer: ByteBuffer) = ByteVector(buffer) def apply(bs: GenTraversableOnce[Byte]) = ByteVector(bs) def view(bytes: Array[Byte]) = ByteVector(bytes) def view(bytes: ByteBuffer) = ByteVector(bytes) def encodeString(str: String, charset: Charset) = if (str.isEmpty) empty else ByteVector(str getBytes charset) def encodeStringStrict(str: String, charset: Charset) = ByteVector.encodeString(str)(charset) ///////////////// QUERY /////////////////// def size(value: ByteVector) = value.size def byteAt(value: ByteVector, ix: Long) = value(ix) def indexOfSlice(value: ByteVector, slice: ByteVector, startIx: Long) = value.indexOfSlice(slice, startIx) ///////////////// TRANSFORMATION TO ByteVector /////////////////// def update(value: ByteVector, ix: Long, byte: Byte) = value.update(ix, byte) def concat(value: ByteVector, other: ByteVector) = value ++ other def concat(value: ByteVector, byte: Byte) = value :+ byte def concat(byte: Byte, value: ByteVector) = byte +: value def drop(value: ByteVector, n: Long) = value.drop(n) def take(value: ByteVector, n: Long) = value.take(n) def map(value: ByteVector, f: Byte ⇒ Byte) = value.map(f) def reverse(value: ByteVector) = value.reverse def compact(value: ByteVector) = value.compact ///////////////// TRANSFORMATION TO OTHER TYPES /////////////////// def toArray(value: ByteVector) = value.toArray def copyToArray(value: ByteVector, xs: Array[Byte], offset: Int) = value.copyToArray(xs, offset) def copyToArray(value: ByteVector, sourceOffset: Long, xs: Array[Byte], destOffset: Int, len: Int) = value.copyToArray(xs, destOffset, sourceOffset, len) def copyToBuffer(value: ByteVector, buffer: ByteBuffer): Int = value.copyToBuffer(buffer) def copyToOutputStream(value: ByteVector, s: OutputStream) = value.copyToStream(s) def toByteBuffer(value: ByteVector) = value.toByteBuffer def toIndexedSeq(value: ByteVector): IndexedSeq[Byte] = value.toIndexedSeq def toSeq(value: ByteVector): Seq[Byte] = value.toSeq def decodeString(value: ByteVector, charset: Charset): Either[CharacterCodingException, String] = value.decodeString(charset) ///////////////// ITERATION /////////////////// def foldLeft[A](value: ByteVector, z: A, f: (A, Byte) ⇒ A) = value.foldLeft(z)(f) def foldRight[A](value: ByteVector, z: A, f: (Byte, A) ⇒ A) = value.foldRight(z)(f) def foreach(value: ByteVector, f: Byte ⇒ Unit) = value.foreach(f) }
Example 2
Source File: WatcherTypes.scala From eclair with Apache License 2.0 | 5 votes |
package fr.acinq.eclair.blockchain import akka.actor.ActorRef import fr.acinq.bitcoin.Crypto.PublicKey import fr.acinq.bitcoin.{ByteVector32, Script, ScriptWitness, Transaction} import fr.acinq.eclair.channel.BitcoinEvent import fr.acinq.eclair.wire.ChannelAnnouncement import scodec.bits.ByteVector import scala.util.{Failure, Success, Try} final case class PublishAsap(tx: Transaction) final case class ValidateRequest(ann: ChannelAnnouncement) sealed trait UtxoStatus object UtxoStatus { case object Unspent extends UtxoStatus case class Spent(spendingTxConfirmed: Boolean) extends UtxoStatus } final case class ValidateResult(c: ChannelAnnouncement, fundingTx: Either[Throwable, (Transaction, UtxoStatus)]) final case class GetTxWithMeta(txid: ByteVector32) final case class GetTxWithMetaResponse(txid: ByteVector32, tx_opt: Option[Transaction], lastBlockTimestamp: Long) // @formatter:on
Example 3
Source File: NodeURI.scala From eclair with Apache License 2.0 | 5 votes |
package fr.acinq.eclair.io import com.google.common.net.HostAndPort import fr.acinq.bitcoin.Crypto.PublicKey import scodec.bits.ByteVector import scala.util.{Failure, Success, Try} case class NodeURI(nodeId: PublicKey, address: HostAndPort) { override def toString: String = s"$nodeId@$address" } object NodeURI { val DEFAULT_PORT = 9735 @throws[IllegalArgumentException] def parse(uri: String): NodeURI = { uri.split("@") match { case Array(nodeId, address) => (Try(PublicKey(ByteVector.fromValidHex(nodeId))), Try(HostAndPort.fromString(address).withDefaultPort(DEFAULT_PORT))) match { case (Success(pk), Success(hostAndPort)) => NodeURI(pk, hostAndPort) case (Failure(_), _) => throw new IllegalArgumentException("Invalid node id") case (_, Failure(_)) => throw new IllegalArgumentException("Invalid host:port") } case _ => throw new IllegalArgumentException("Invalid uri, should be nodeId@host:port") } } }
Example 4
Source File: WaitForFundingCreatedInternalStateSpec.scala From eclair with Apache License 2.0 | 5 votes |
package fr.acinq.eclair.channel.states.b import akka.testkit.{TestFSMRef, TestProbe} import fr.acinq.bitcoin.{ByteVector32, Satoshi} import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.blockchain.{MakeFundingTxResponse, TestWallet} import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.wire._ import fr.acinq.eclair.{TestConstants, TestKitBaseClass} import org.scalatest.Outcome import org.scalatest.funsuite.FixtureAnyFunSuiteLike import scodec.bits.ByteVector import scala.concurrent.duration._ import scala.concurrent.{Future, Promise} class WaitForFundingCreatedInternalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with StateTestsHelperMethods { case class FixtureParam(alice: TestFSMRef[State, Data, Channel], alice2bob: TestProbe, bob2alice: TestProbe, alice2blockchain: TestProbe) override def withFixture(test: OneArgTest): Outcome = { val noopWallet = new TestWallet { override def makeFundingTx(pubkeyScript: ByteVector, amount: Satoshi, feeRatePerKw: Long): Future[MakeFundingTxResponse] = Promise[MakeFundingTxResponse].future // will never be completed } val setup = init(wallet = noopWallet) import setup._ val aliceInit = Init(Alice.channelParams.features) val bobInit = Init(Bob.channelParams.features) within(30 seconds) { alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD) bob ! INPUT_INIT_FUNDEE(ByteVector32.Zeroes, Bob.channelParams, bob2alice.ref, aliceInit) alice2bob.expectMsgType[OpenChannel] alice2bob.forward(bob) bob2alice.expectMsgType[AcceptChannel] bob2alice.forward(alice) awaitCond(alice.stateName == WAIT_FOR_FUNDING_INTERNAL) withFixture(test.toNoArgTest(FixtureParam(alice, alice2bob, bob2alice, alice2blockchain))) } } test("recv Error") { f => import f._ alice ! Error(ByteVector32.Zeroes, "oops") awaitCond(alice.stateName == CLOSED) } test("recv CMD_CLOSE") { f => import f._ alice ! CMD_CLOSE(None) awaitCond(alice.stateName == CLOSED) } }
Example 5
Source File: FuzzyPipe.scala From eclair with Apache License 2.0 | 5 votes |
package fr.acinq.eclair.channel import akka.actor.{Actor, ActorLogging, ActorRef, Stash} import fr.acinq.eclair.Features import fr.acinq.eclair.channel.Commitments.msg2String import fr.acinq.eclair.wire.{Init, LightningMessage} import scodec.bits.ByteVector import scala.concurrent.duration._ import scala.util.Random class FuzzyPipe(fuzzy: Boolean) extends Actor with Stash with ActorLogging { import scala.concurrent.ExecutionContext.Implicits.global def receive = { case (a: ActorRef, b: ActorRef) => unstashAll() context become connected(a, b, 10) case _ => stash() } def stayOrDisconnect(a: ActorRef, b: ActorRef, countdown: Int): Unit = { if (!fuzzy) context become connected(a, b, countdown - 1) // fuzzy mode disabled, we never disconnect else if (countdown > 1) context become connected(a, b, countdown - 1) else { log.debug("DISCONNECTED") a ! INPUT_DISCONNECTED b ! INPUT_DISCONNECTED context.system.scheduler.scheduleOnce(100 millis, self, 'reconnect) context become disconnected(a, b) } } def connected(a: ActorRef, b: ActorRef, countdown: Int): Receive = { case msg: LightningMessage if sender() == a => log.debug(f"A ---${msg2String(msg)}%-6s--> B") b forward msg stayOrDisconnect(a, b, countdown) case msg: LightningMessage if sender() == b => log.debug(f"A <--${msg2String(msg)}%-6s--- B") a forward msg stayOrDisconnect(a, b, countdown) } def disconnected(a: ActorRef, b: ActorRef): Receive = { case msg: LightningMessage if sender() == a => // dropped log.info(f"A ---${msg2String(msg)}%-6s-X") case msg: LightningMessage if sender() == b => // dropped log.debug(f" X-${msg2String(msg)}%-6s--- B") case 'reconnect => log.debug("RECONNECTED") val dummyInit = Init(Features.empty) a ! INPUT_RECONNECTED(self, dummyInit, dummyInit) b ! INPUT_RECONNECTED(self, dummyInit, dummyInit) context become connected(a, b, Random.nextInt(40)) } }
Example 6
Source File: SqliteChannelsDbSpec.scala From eclair with Apache License 2.0 | 5 votes |
package fr.acinq.eclair.db import fr.acinq.bitcoin.ByteVector32 import fr.acinq.eclair.db.sqlite.SqliteUtils.{getVersion, using} import fr.acinq.eclair.db.sqlite.{SqliteChannelsDb, SqlitePendingRelayDb} import fr.acinq.eclair.wire.ChannelCodecs.stateDataCodec import fr.acinq.eclair.wire.ChannelCodecsSpec import fr.acinq.eclair.{CltvExpiry, TestConstants} import org.scalatest.funsuite.AnyFunSuite import org.sqlite.SQLiteException import scodec.bits.ByteVector class SqliteChannelsDbSpec extends AnyFunSuite { test("init sqlite 2 times in a row") { val sqlite = TestConstants.sqliteInMemory() val db1 = new SqliteChannelsDb(sqlite) val db2 = new SqliteChannelsDb(sqlite) } test("add/remove/list channels") { val sqlite = TestConstants.sqliteInMemory() val db = new SqliteChannelsDb(sqlite) new SqlitePendingRelayDb(sqlite) // needed by db.removeChannel val channel = ChannelCodecsSpec.normal val commitNumber = 42 val paymentHash1 = ByteVector32.Zeroes val cltvExpiry1 = CltvExpiry(123) val paymentHash2 = ByteVector32(ByteVector.fill(32)(1)) val cltvExpiry2 = CltvExpiry(656) intercept[SQLiteException](db.addHtlcInfo(channel.channelId, commitNumber, paymentHash1, cltvExpiry1)) // no related channel assert(db.listLocalChannels().toSet === Set.empty) db.addOrUpdateChannel(channel) db.addOrUpdateChannel(channel) assert(db.listLocalChannels() === List(channel)) assert(db.listHtlcInfos(channel.channelId, commitNumber).toList == Nil) db.addHtlcInfo(channel.channelId, commitNumber, paymentHash1, cltvExpiry1) db.addHtlcInfo(channel.channelId, commitNumber, paymentHash2, cltvExpiry2) assert(db.listHtlcInfos(channel.channelId, commitNumber).toList == List((paymentHash1, cltvExpiry1), (paymentHash2, cltvExpiry2))) assert(db.listHtlcInfos(channel.channelId, 43).toList == Nil) db.removeChannel(channel.channelId) assert(db.listLocalChannels() === Nil) assert(db.listHtlcInfos(channel.channelId, commitNumber).toList == Nil) } test("migrate channel database v1 -> v2") { val sqlite = TestConstants.sqliteInMemory() // create a v1 channels database using(sqlite.createStatement()) { statement => getVersion(statement, "channels", 1) statement.execute("PRAGMA foreign_keys = ON") statement.executeUpdate("CREATE TABLE IF NOT EXISTS local_channels (channel_id BLOB NOT NULL PRIMARY KEY, data BLOB NOT NULL)") statement.executeUpdate("CREATE TABLE IF NOT EXISTS htlc_infos (channel_id BLOB NOT NULL, commitment_number BLOB NOT NULL, payment_hash BLOB NOT NULL, cltv_expiry INTEGER NOT NULL, FOREIGN KEY(channel_id) REFERENCES local_channels(channel_id))") statement.executeUpdate("CREATE INDEX IF NOT EXISTS htlc_infos_idx ON htlc_infos(channel_id, commitment_number)") } // insert 1 row val channel = ChannelCodecsSpec.normal val data = stateDataCodec.encode(channel).require.toByteArray using(sqlite.prepareStatement("INSERT INTO local_channels VALUES (?, ?)")) { statement => statement.setBytes(1, channel.channelId.toArray) statement.setBytes(2, data) statement.executeUpdate() } // check that db migration works val db = new SqliteChannelsDb(sqlite) using(sqlite.createStatement()) { statement => assert(getVersion(statement, "channels", 1) == 2) // version changed from 1 -> 2 } assert(db.listLocalChannels() === List(channel)) } }
Example 7
Source File: BinaryCodecs.scala From skunk with MIT License | 5 votes |
// Copyright (c) 2018-2020 by Rob Norris // This software is licensed under the MIT License (MIT). // For more information see LICENSE or https://opensource.org/licenses/MIT package skunk package codec import cats.implicits._ import scodec.bits.ByteVector import skunk.data.Type trait BinaryCodecs { val bytea: Codec[Array[Byte]] = Codec.simple[Array[Byte]]( "\\x" + ByteVector.view(_).toHex, z => ByteVector.fromHex(z.substring(2)).map(_.toArray).fold("Cannot decode bytes from HEX String".asLeft[Array[Byte]])(_.asRight[String]), Type.bytea) } object binary extends BinaryCodecs
Example 8
Source File: HashTransformationSpec.scala From swave with Mozilla Public License 2.0 | 5 votes |
package swave.core.hash import scodec.bits.ByteVector import swave.compat.scodec._ import swave.core._ class HashTransformationSpec extends SwaveSpec { import swave.core.text._ implicit val env = StreamEnv() "HashTransformations" - { "md5" in { Spout .one("swave rocks!") .utf8Encode .md5 .drainToHead() .value .get .get shouldEqual ByteVector.fromHex("e1b2b603f9cca4a909c07d42a5788fe3").get } } }
Example 9
Source File: TextTransformationSpec.scala From swave with Mozilla Public License 2.0 | 5 votes |
package swave.core.text import scala.concurrent.duration._ import scodec.bits.ByteVector import swave.compat.scodec._ import swave.core._ import swave.core.util._ class TextTransformationSpec extends SwaveSpec { implicit val env = StreamEnv() import env.defaultDispatcher val largeText = """Es war einmal, zur Zeit t=t0, ein armer rechtschaffener Vierpol namens Eddy Wirbelstrom. Er bewohnte einen |bescheiden möbilierten Hohlraum im Dielektrikum mit fließend kalten und warmen Sättigungsstrom. Leider mußte er |während der kalten Jahreszeit für die Erwärmung der Sperrschicht noch extra bezahlen. Seinen Lebensunterhalt |bestritt er mit einer Verstärkerzucht auf Transistorbasis. | |Eddy Wirbelstrom liebte mit der ganzen Kraft seiner Übertragungsfunktion - Ionchen! | |Die induktivste Spule mit dem kleinsten Verlustwinkel im ganzen Kreise und Tochter der einflußreichen EMKs. |Ihr remanenter Ferritkörper, ihre symmetrischen Netzintegrale, ihre überaus harmonischen Oberwellen - besonders |der Sinus - beeindruckten selbst die Suszeptibilität ausgedienter Leidener Flaschen, was viel heißen will. |Die jungfräulichen Kurven Ionchens waren auch wirklich sehr steil. | |Ionchens Vater, Cosinus Phi, ein bekannter industrieller Leistungsfaktor, hatte allerdings bereits konkrete |Schaltpläne für die Zukunft t >> t0 seiner Tochter. Sie sollte nur einer anerkannten Kapazität mit |ausgeprägtem Nennwert angeschlossen werden, aber wie so oft während der Lebensdauer L hatte auch diese Masche |einen Knoten, denn der Zufallstrieb wollte es anders. | |Als Ionchen eines Tages, zur Zeit t=t1, auf ihrem Picofarad vom Frisiersalon nach Hause fuhr (sie hatte sich eine |neue Stehwelle legen lassen), da geriet ihr ein Sägezahn in die Siebkette. Aber Eddy Wirbelstrom, der die Gegend |periodisch frequentierte, eilte mit minimaler Laufzeit hinzu, und es gelang ihm, Ionchens Kippschwingung noch |vor dem Maximum der Amplitude abzufangen, gleichzurichten und so die Resonanzkatastrophe zu verhindern. | |Es ist sicherlich nicht dem Zufall z1 zuzuschreiben, daß sie sich schon zur Zeit t = t1 + dt wiedersahen. |Eddy lud Ionchen zum Abendessen ins "Goldene Integral" ein. Aber das Integral war wie immer geschlossen. |"Macht nichts", sagte Ionchen, "ich habe zu Mittag gut gegessen und die Sättigungsinduktion hat bis jetzt |angehalten. Außerdem muß ich auf meine Feldlinie achten." Unter irgendeinem Vorwand lud Eddy sie dann zu einer |Rundfahrt im Rotor ein. Aber Ionchen lehnte ab: "Mir wird bei der zweiten Ableitung immer so leicht übel." |So unternahmen sie, ganz entgegen den Schaltplänen von Vater Cosinus Phi, einen kleinen Frequenzgang entlang dem |nahegelegenen Streufluß. | |Der Abend senkte sich über die komplexe Ebene und im imaginären Raum erglänzten die Sternschaltungen. |Eddy und Ionchen genossen die Isolierung vom lauten Getriebe der Welt und ließen ihre Blicke gegen 0 laufen. |Ein einsamer Modulationsbrummer flog vorbei, sanft plätscherten die elektromagnetischen Wellen und leise sang |eine Entstördrossel. | |Als sie an der Wheatston-Brücke angelangt waren, dort, wo der Blindstrom in den Streufluß mündet, lehnten sie |sich ans Gitter. Da nahm Eddy Wirbelstrom seinen ganzen Durchgriff zusammen und emittierte: "Bei Gauß!", |worauf Ionchen hauchte: "Deine lose Rückkopplung hat es mir angetan." Ihr Kilohertz schlug heftig. | |Der Informationsgehalt dieser Nachricht durchflutete Eddy. Die Summe über alle Theta, von Theta = 0 bis zu diesem |Ereignis war zu konvergent und beide entglitten der Kontrolle ihrer Zeitkonstanten. |Im Überschwange des jungen Glücks erreichten sie vollausgesteuert die Endstufen. |Und wenn sie nicht gedämpft wurden, so schwingen sie heute noch.""".stripMargin.replace("\r\n", "\n") "TextTransformations" - { "utf8decode" in { for (_ <- 1 to 10) { val random = XorShiftRandom() Spout(largeText.getBytes(UTF8).iterator) .injectSequential() .flatMap(_.take(random.nextLong(32)).drainToVector(32).map(ByteVector(_))) .utf8Decode .async() .drainToMkString(1000) .await(3.seconds) shouldEqual largeText } } "utf8encode" in { for (_ <- 1 to 10) { val random = XorShiftRandom() Spout(largeText.iterator) .injectSequential() .flatMap(_.take(random.nextLong(32)).drainToMkString(32)) .utf8Encode .async() .drainFolding(ByteVector.empty)(_ ++ _) .await() shouldEqual ByteVector(largeText getBytes UTF8) } } "lines" in { for (_ <- 1 to 1) { val random = XorShiftRandom() Spout(largeText.iterator) .injectSequential() .flatMap(_.take(random.nextLong(32)).drainToMkString(32)) .lines .async() .drainToVector(1000) .await() shouldEqual largeText.split('\n') } } } }
Example 10
Source File: FileDrainSpec.scala From swave with Mozilla Public License 2.0 | 5 votes |
package swave.core.io.files import java.nio.file.{Files, Path} import scala.concurrent.duration._ import scodec.bits.ByteVector import swave.compat.scodec._ import swave.core.util._ import swave.core._ class FileDrainSpec extends SwaveSpec { import swave.core.io.files._ implicit val env = StreamEnv() val TestLines = List[String]( "a" * 1000 + "\n", "b" * 1000 + "\n", "c" * 1000 + "\n", "d" * 1000 + "\n", "e" * 1000 + "\n", "f" * 1000 + "\n") val TestBytes = TestLines.map(ByteVector.encodeAscii(_).right.get) "Drain.toPath must" - { "write lines to a short file" in withTempPath(create = true) { path ⇒ val result = Spout.one(ByteVector("abc" getBytes UTF8)).drainTo(Drain.toPath(path, chunkSize = 512)) result.await(5.seconds) shouldEqual 3 verifyFileContents(path, "abc") } "write lines to a long file" in withTempPath(create = true) { path ⇒ val result = Spout(TestBytes).drainTo(Drain.toPath(path, chunkSize = 512)) result.await(5.seconds) shouldEqual 6006 verifyFileContents(path, TestLines mkString "") } "create new file if required" in withTempPath(create = false) { path ⇒ val result = Spout(TestBytes).drainTo(Drain.toPath(path, chunkSize = 512)) result.await(5.seconds) shouldEqual 6006 verifyFileContents(path, TestLines mkString "") } } private def withTempPath(create: Boolean)(block: Path ⇒ Unit): Unit = { val targetFile = Files.createTempFile("file-sink", ".tmp") if (!create) Files.delete(targetFile) try block(targetFile) finally Files.delete(targetFile) } private def verifyFileContents(path: Path, contents: String): Unit = { val out = Files.readAllBytes(path) new String(out) shouldEqual contents } }
Example 11
Source File: ElectrumEclairWallet.scala From eclair with Apache License 2.0 | 5 votes |
package fr.acinq.eclair.blockchain.electrum import akka.actor.{ActorRef, ActorSystem} import akka.pattern.ask import fr.acinq.bitcoin.{ByteVector32, Crypto, Satoshi, Script, Transaction, TxOut} import fr.acinq.eclair.addressToPublicKeyScript import fr.acinq.eclair.blockchain.electrum.ElectrumClient.BroadcastTransaction import fr.acinq.eclair.blockchain.electrum.ElectrumWallet._ import fr.acinq.eclair.blockchain.{EclairWallet, MakeFundingTxResponse, OnChainBalance} import grizzled.slf4j.Logging import scodec.bits.ByteVector import scala.concurrent.{ExecutionContext, Future} class ElectrumEclairWallet(val wallet: ActorRef, chainHash: ByteVector32)(implicit system: ActorSystem, ec: ExecutionContext, timeout: akka.util.Timeout) extends EclairWallet with Logging { override def getBalance: Future[OnChainBalance] = (wallet ? GetBalance).mapTo[GetBalanceResponse].map(balance => OnChainBalance(balance.confirmed, balance.unconfirmed)) override def getReceiveAddress: Future[String] = (wallet ? GetCurrentReceiveAddress).mapTo[GetCurrentReceiveAddressResponse].map(_.address) override def getReceivePubkey(receiveAddress: Option[String] = None): Future[Crypto.PublicKey] = Future.failed(new RuntimeException("Not implemented")) def getXpub: Future[GetXpubResponse] = (wallet ? GetXpub).mapTo[GetXpubResponse] override def makeFundingTx(pubkeyScript: ByteVector, amount: Satoshi, feeRatePerKw: Long): Future[MakeFundingTxResponse] = { val tx = Transaction(version = 2, txIn = Nil, txOut = TxOut(amount, pubkeyScript) :: Nil, lockTime = 0) (wallet ? CompleteTransaction(tx, feeRatePerKw)).mapTo[CompleteTransactionResponse].map { case CompleteTransactionResponse(tx1, fee1, None) => MakeFundingTxResponse(tx1, 0, fee1) case CompleteTransactionResponse(_, _, Some(error)) => throw error } } override def commit(tx: Transaction): Future[Boolean] = (wallet ? BroadcastTransaction(tx)) flatMap { case ElectrumClient.BroadcastTransactionResponse(tx, None) => //tx broadcast successfully: commit tx wallet ? CommitTransaction(tx) case ElectrumClient.BroadcastTransactionResponse(tx, Some(error)) if error.message.contains("transaction already in block chain") => // tx was already in the blockchain, that's weird but it is OK wallet ? CommitTransaction(tx) case ElectrumClient.BroadcastTransactionResponse(_, Some(error)) => //tx broadcast failed: cancel tx logger.error(s"cannot broadcast tx ${tx.txid}: $error") wallet ? CancelTransaction(tx) case ElectrumClient.ServerError(ElectrumClient.BroadcastTransaction(tx), error) => //tx broadcast failed: cancel tx logger.error(s"cannot broadcast tx ${tx.txid}: $error") wallet ? CancelTransaction(tx) } map { case CommitTransactionResponse(_) => true case CancelTransactionResponse(_) => false } def sendPayment(amount: Satoshi, address: String, feeRatePerKw: Long): Future[String] = { val publicKeyScript = Script.write(addressToPublicKeyScript(address, chainHash)) val tx = Transaction(version = 2, txIn = Nil, txOut = TxOut(amount, publicKeyScript) :: Nil, lockTime = 0) (wallet ? CompleteTransaction(tx, feeRatePerKw)) .mapTo[CompleteTransactionResponse] .flatMap { case CompleteTransactionResponse(tx, _, None) => commit(tx).map { case true => tx.txid.toString() case false => throw new RuntimeException(s"could not commit tx=$tx") } case CompleteTransactionResponse(_, _, Some(error)) => throw error } } def sendAll(address: String, feeRatePerKw: Long): Future[(Transaction, Satoshi)] = { val publicKeyScript = Script.write(addressToPublicKeyScript(address, chainHash)) (wallet ? SendAll(publicKeyScript, feeRatePerKw)) .mapTo[SendAllResponse] .map { case SendAllResponse(tx, fee) => (tx, fee) } } override def rollback(tx: Transaction): Future[Boolean] = (wallet ? CancelTransaction(tx)).map(_ => true) override def doubleSpent(tx: Transaction): Future[Boolean] = { (wallet ? IsDoubleSpent(tx)).mapTo[IsDoubleSpentResponse].map(_.isDoubleSpent) } }
Example 12
Source File: ReprFormat.scala From polynote with Apache License 2.0 | 5 votes |
package polynote.data import scodec.bits.{BitVector, ByteVector} import shapeless.{Generic, HList, HNil, Lazy, ::} import scala.collection.GenTraversable trait ReprFormat[T] extends (T => ByteVector) object ReprFormat extends ReprFormat0 { final case class instance[T](fn: T => ByteVector) extends ReprFormat[T] { def apply(t: T): ByteVector = fn(t) } private val one = ByteVector.fromByte(1) private val zero = ByteVector.fromByte(0) implicit val byteFormat: ReprFormat[Byte] = instance(ByteVector.fromByte) implicit val boolFormat: ReprFormat[Boolean] = instance(b => if (b) one else zero) implicit val shortFormat: ReprFormat[Short] = instance(ByteVector.fromShort(_)) implicit val intFormat: ReprFormat[Int] = instance(ByteVector.fromInt(_)) implicit val longFormat: ReprFormat[Long] = instance(ByteVector.fromLong(_)) implicit val floatFormat: ReprFormat[Float] = instance(f => ByteVector.fromInt(java.lang.Float.floatToIntBits(f))) implicit val doubleFormat: ReprFormat[Double] = instance(d => ByteVector.fromLong(java.lang.Double.doubleToLongBits(d))) implicit val stringFormat: ReprFormat[String] = instance(str => ByteVector.encodeUtf8(str).fold(throw _, identity)) implicit val byteArrayFormat: ReprFormat[Array[Byte]] = instance(ByteVector(_)) implicit val byteVectorFormat: ReprFormat[ByteVector] = instance(identity) implicit val bitVectorFormat: ReprFormat[BitVector] = instance(_.toByteVector) implicit def arrayFormat[A](implicit elFormat: ReprFormat[A]): ReprFormat[Array[A]] = instance { arr => arr.foldLeft(ByteVector.fromInt(arr.length)) { (accum: ByteVector, next: A) => accum ++ elFormat(next) } } implicit def traversableFormat[F[X] <: GenTraversable[X], A](implicit elFormat: ReprFormat[A]): ReprFormat[F[A]] = instance { arr => arr.foldLeft(ByteVector.fromInt(arr.size)) { (accum, next) => accum ++ elFormat(next) } } implicit def optionalFormat[A](implicit elFormat: ReprFormat[A]): ReprFormat[Option[A]] = instance { case Some(el) => one ++ elFormat(el) case None => zero } implicit val hnilFormat: ReprFormat[HNil] = instance(_ => ByteVector.empty) implicit def hlistFormat[H, T <: HList](implicit formatH: ReprFormat[H], formatT: ReprFormat[T]): ReprFormat[H :: T] = instance { case h :: t => formatH(h) ++ formatT(t) } } private[data] trait ReprFormat0 { self: ReprFormat.type => implicit def struct[A, L <: HList](implicit gen: Generic.Aux[A, L], formatL: Lazy[ReprFormat[L]]): ReprFormat[A] = instance(a => formatL.value(gen.to(a))) }
Example 13
Source File: DataTypeCodec.scala From polynote with Apache License 2.0 | 5 votes |
package polynote.kernel import java.nio.ByteBuffer import java.nio.charset.StandardCharsets import polynote.runtime._ import scodec.Codec import scodec.bits.ByteVector import scodec.codecs._ import scodec.codecs.implicits._ import shapeless.cachedImplicit object DataTypeCodec { implicit val byteDiscriminator: Discriminator[DataType, ByteType.type, Byte] = Discriminator(0) implicit val boolDiscriminator: Discriminator[DataType, BoolType.type, Byte] = Discriminator(1) implicit val shortDiscriminator: Discriminator[DataType, ShortType.type, Byte] = Discriminator(2) implicit val intDiscriminator: Discriminator[DataType, IntType.type, Byte] = Discriminator(3) implicit val longDiscriminator: Discriminator[DataType, LongType.type, Byte] = Discriminator(4) implicit val floatDiscriminator: Discriminator[DataType, FloatType.type, Byte] = Discriminator(5) implicit val doubleDiscriminator: Discriminator[DataType, DoubleType.type, Byte] = Discriminator(6) implicit val binaryDiscriminator: Discriminator[DataType, BinaryType.type, Byte] = Discriminator(7) implicit val stringDiscriminator: Discriminator[DataType, StringType.type, Byte] = Discriminator(8) implicit val structDiscriminator: Discriminator[DataType, StructType, Byte] = Discriminator(9) implicit val optionalDiscriminator: Discriminator[DataType, OptionalType, Byte] = Discriminator(10) implicit val arrayDiscriminator: Discriminator[DataType, ArrayType, Byte] = Discriminator(11) //implicit val dateDiscriminator: Discriminator[DataType, DateType.type, Byte] = Discriminator(12) //implicit val timestampDiscriminator: Discriminator[DataType, TimestampType.type, Byte] = Discriminator(13) implicit val typeDiscriminator: Discriminator[DataType, TypeType.type, Byte] = Discriminator(14) implicit val mapDiscriminator: Discriminator[DataType, MapType, Byte] = Discriminator(15) implicit val dataTypeDiscriminated: Discriminated[DataType, Byte] = Discriminated(byte) implicit val dataTypeCodec: Codec[DataType] = cachedImplicit } object ValueReprCodec { import DataTypeCodec.dataTypeCodec implicit val valueReprDiscriminated: Discriminated[ValueRepr, Byte] = Discriminated(byte) implicit val stringRepr: Discriminator[ValueRepr, StringRepr, Byte] = Discriminator(0) implicit val mimeRepr: Discriminator[ValueRepr, MIMERepr, Byte] = Discriminator(1) implicit val dataRepr: Discriminator[ValueRepr, DataRepr, Byte] = Discriminator(2) implicit val lazyDataRepr: Discriminator[ValueRepr, LazyDataRepr, Byte] = Discriminator(3) implicit val updatingDataRepr: Discriminator[ValueRepr, UpdatingDataRepr, Byte] = Discriminator(4) implicit val streamingDataRepr: Discriminator[ValueRepr, StreamingDataRepr, Byte] = Discriminator(5) implicit val streamingDataReprCodec: Codec[StreamingDataRepr] = cachedImplicit implicit val byteBufferCodec: Codec[ByteBuffer] = variableSizeBytes(int32, bytes).xmap(_.toByteBuffer, ByteVector.apply) implicit val codec: Codec[ValueRepr] = cachedImplicit } object TableOpCodec { implicit val tableOpDiscriminated: Discriminated[TableOp, Byte] = Discriminated(byte) implicit val groupAgg: Discriminator[TableOp, GroupAgg, Byte] = Discriminator(0) implicit val quantileBin: Discriminator[TableOp, QuantileBin, Byte] = Discriminator(1) implicit val select: Discriminator[TableOp, Select, Byte] = Discriminator(2) implicit val tableOpCodec: Codec[TableOp] = cachedImplicit }
Example 14
Source File: RecoverLog.scala From polynote with Apache License 2.0 | 5 votes |
package polynote import java.nio.channels.FileChannel import java.nio.file.{Files, Paths, StandardOpenOption} import java.time.Instant import cats.effect.Effect import polynote.app.{Args, MainArgs} import polynote.kernel.logging.Logging import polynote.messages.{Message, Notebook, NotebookUpdate, ShortList} import polynote.server.AppEnv import zio.{Ref, Runtime, Task, UIO, ZIO} import zio.ZIO.effectTotal import zio.blocking.effectBlocking import fs2.Stream import polynote.server.repository.{FileBasedRepository, NotebookContent} import polynote.server.repository.format.ipynb.IPythonFormat import polynote.server.repository.fs.WAL import polynote.server.taskConcurrent import scodec.bits.ByteVector import scodec.stream.decode import scodec.codecs import scodec.stream.decode.StreamDecoder object RecoverLog { def replay(messages: Stream[Task, (Instant, Message)], ref: Ref[Notebook], log: Logging.Service): UIO[Unit] = messages.map(_._2).evalMap { case nb: Notebook => ref.set(nb) case upd: NotebookUpdate => ref.update { nb => try { upd.applyTo(nb) } catch { case err: Throwable => log.errorSync(Some("Dropped update because an error occurred when applying it"), err) nb } } case _ => ZIO.unit }.compile.drain.catchAll { err => log.error(Some("Error occurred while replaying the log; printing the final state anyway."), err) } def main(implicit ev: Effect[Task]): ZIO[AppEnv, String, Int] = for { args <- ZIO.access[MainArgs](_.get[Args].rest) path <- ZIO(args.head).flatMap(pathStr => effectBlocking(Paths.get(pathStr).toRealPath())).orDie is <- effectBlocking(FileChannel.open(path, StandardOpenOption.READ)).orDie log <- Logging.access _ <- Logging.info(s"Reading log entries from ${path}...") messages = WAL.decoder.decodeMmap(is) ref <- Ref.make(Notebook("", ShortList.Nil, None)) _ <- replay(messages, ref, log) format = new IPythonFormat result <- ref.get encoded <- format.encodeNotebook(NotebookContent(result.cells, result.config)).orDie _ <- effectTotal(println(encoded)) } yield 0 }
Example 15
package polynote.server package repository.fs import java.nio.ByteBuffer import java.nio.charset.StandardCharsets import java.time.Instant import polynote.messages.{Message, Notebook} import scodec.bits.{BitVector, ByteVector} import scodec.{Attempt, Codec, codecs} import scodec.stream.decode import scodec.stream.decode.StreamDecoder import zio.{RIO, Task, ZIO} import zio.blocking.Blocking import zio.clock.{Clock, currentDateTime} import scala.util.Try object WAL { val WALMagicNumber: Array[Byte] = "PNWAL".getBytes(StandardCharsets.US_ASCII) val WALVersion: Short = 1 // Timestamp for each update is stored in 32 bits unsigned, epoch UTC seconds. // So we'll have to change the format by February of 2106. Apologies to my great-great-great grandchildren. private val instantCodec = codecs.uint32.exmap[Instant]( epochSeconds => Attempt.fromTry(Try(Instant.ofEpochSecond(epochSeconds))), instant => Attempt.successful(instant.getEpochSecond) ) def encodeTimestamp(instant: Instant): Task[BitVector] = ZIO.fromEither(instantCodec.encode(instant).toEither) .mapError(err => new RuntimeException(err.message)) val messageCodec: Codec[(Instant, Message)] = codecs.variableSizeBytes(codecs.int32, instantCodec ~ Message.codec) val decoder: StreamDecoder[(Instant, Message)] = { val readMagic = decode.once(codecs.constant(ByteVector(WALMagicNumber))) val readVersion = decode.once(codecs.int16) def readMessages(version: Int): StreamDecoder[(Instant, Message)] = version match { case 1 => decode.many(messageCodec) case v => decode.raiseError(new Exception(s"Unknown WAL version $v")) } for { _ <- readMagic ver <- readVersion message <- readMessages(ver) } yield message } trait WALWriter { protected def append(bytes: Array[Byte]): RIO[Blocking, Unit] = append(ByteBuffer.wrap(bytes)) protected def append(bytes: BitVector): RIO[Blocking, Unit] = append(bytes.toByteBuffer) protected def append(bytes: ByteBuffer): RIO[Blocking, Unit] def writeHeader(notebook: Notebook): RIO[Blocking with Clock, Unit] = append(WALMagicNumber) *> append(BitVector.fromShort(WALVersion)) *> appendMessage(notebook.withoutResults) def appendMessage(message: Message): RIO[Blocking with Clock, Unit] = for { ts <- currentDateTime.map(_.toInstant) bytes <- ZIO.fromEither(messageCodec.encode((ts, message)).toEither).mapError(err => new RuntimeException(err.message)) _ <- append(bytes) } yield () def sync(): RIO[Blocking, Unit] def close(): RIO[Blocking, Unit] } object WALWriter { object NoWAL extends WALWriter { override protected def append(bytes: ByteBuffer): RIO[Blocking, Unit] = ZIO.unit override def sync(): RIO[Blocking, Unit] = ZIO.unit override def close(): RIO[Blocking, Unit] = ZIO.unit } } }
Example 16
Source File: Netty.scala From scalaz-netty with Apache License 2.0 | 5 votes |
package scalaz package netty import java.net.InetSocketAddress import java.util.concurrent.ExecutorService import _root_.io.netty.channel._ import scodec.bits.ByteVector import scalaz.concurrent._ import scalaz.stream._ object Netty { def server(bind: InetSocketAddress, config: ServerConfig = ServerConfig.Default)(implicit pool: ExecutorService = Strategy.DefaultExecutorService, S: Strategy): Process[Task, Process[Task, Exchange[ByteVector, ByteVector]]] = { Process.bracket(Server(bind, config))(s => Process.eval(s.shutdown).drain) { server: Server => server.listen } } def connect(to: InetSocketAddress, config: ClientConfig = ClientConfig.Default)(implicit pool: ExecutorService = Strategy.DefaultExecutorService, S: Strategy): Process[Task, Exchange[ByteVector, ByteVector]] = { Process.bracket(Client(to, config))(_.shutdown) { client: Client => Process(Exchange(client.read, client.write)) } } private[netty] def toTask(f: ChannelFuture)(implicit pool: ExecutorService): Task[Unit] = fork { Task async { (cb: (Throwable \/ Unit) => Unit) => f.addListener(new ChannelFutureListener { def operationComplete(f: ChannelFuture): Unit = { if (f.isSuccess) cb(\/-(())) else cb(-\/(f.cause)) } }) } } private def fork[A](t: Task[A])(implicit pool: ExecutorService = Strategy.DefaultExecutorService): Task[A] = { Task async { cb => t unsafePerformAsync { either => pool.submit(new Runnable { def run(): Unit = cb(either) }) () } } } }
Example 17
Source File: ModelMatrixEncoding.scala From modelmatrix with Apache License 2.0 | 5 votes |
package com.collective.modelmatrix import java.nio.ByteBuffer import scodec.bits.ByteVector private[modelmatrix] trait Encode[T] { def encode(obj: T): ByteVector } private[modelmatrix] object Encode { def apply[T](f: T => ByteVector): Encode[T] = new Encode[T] { def encode(obj: T): ByteVector = f(obj) } implicit val EncodeShort: Encode[Short] = Encode((short: Short) => ByteVector(ByteBuffer.allocate(2).putShort(short).array())) implicit val EncodeInt: Encode[Int] = Encode((integer: Int) => ByteVector(ByteBuffer.allocate(4).putInt(integer).array())) implicit val EncodeLong: Encode[Long] = Encode((long: Long) => ByteVector(ByteBuffer.allocate(8).putLong(long).array())) implicit val EncodeDouble: Encode[Double] = Encode((double: Double) => ByteVector(ByteBuffer.allocate(8).putDouble(double).array())) implicit val EncodeString: Encode[String] = Encode((string: String) => ByteVector(string.getBytes)) } private[modelmatrix] trait Decode[T] { def decode(bytes: ByteVector): T } private[modelmatrix] object Decode { def apply[T](f: ByteVector => T): Decode[T] = new Decode[T] { def decode(bytes: ByteVector): T = f(bytes) } implicit val DecodeShort: Decode[Short] = Decode(_.toByteBuffer.getShort) implicit val DecodeInt: Decode[Int] = Decode(_.toByteBuffer.getInt) implicit val DecodeLong: Decode[Long] = Decode(_.toByteBuffer.getLong) implicit val DecodeDouble: Decode[Double] = Decode(_.toByteBuffer.getDouble) implicit val DecodeString: Decode[String] = Decode(b => new String(b.toArray)) } class ModelMatrixEncoding { def encode[T: Encode](obj: T): ByteVector = implicitly[Encode[T]].encode(obj) def decode[T: Decode](obj: ByteVector): T = implicitly[Decode[T]].decode(obj) } object ModelMatrixEncoding extends ModelMatrixEncoding
Example 18
Source File: package.scala From modelmatrix with Apache License 2.0 | 5 votes |
package com.collective.modelmatrix import java.sql.Timestamp import java.time.Instant import org.apache.spark.sql.types._ import scodec.bits.ByteVector import slick.driver.PostgresDriver.api._ package object catalog { implicit val instantColumnType = MappedColumnType.base[Instant, java.sql.Timestamp]( instant => Timestamp.from(instant), _.toInstant ) implicit val dataTypeColumnType = MappedColumnType.base[DataType, String]({ case ShortType => "short" case IntegerType => "integer" case LongType => "long" case DoubleType => "double" case StringType => "string" }, { case "short" => ShortType case "integer" => IntegerType case "long" => LongType case "double" => DoubleType case "string" => StringType }) implicit val byteVectorColumnType = MappedColumnType.base[ByteVector, Array[Byte]]( _.toArray, ByteVector.apply ) }
Example 19
Source File: CategoricalColumn.scala From modelmatrix with Apache License 2.0 | 5 votes |
package com.collective.modelmatrix import scodec.bits.ByteVector sealed trait CategoricalColumn { type Self <: CategoricalColumn def columnId: Int def count: Long def cumulativeCount: Long def rebaseColumnId(base: Int): Self } object CategoricalColumn { case class CategoricalValue( columnId: Int, sourceName: String, sourceValue: ByteVector, count: Long, cumulativeCount: Long ) extends CategoricalColumn { type Self = CategoricalValue def rebaseColumnId(base: Int): CategoricalValue = copy(columnId = columnId + base) } case class AllOther( columnId: Int, count: Long, cumulativeCount: Long ) extends CategoricalColumn { type Self = AllOther def rebaseColumnId(base: Int): AllOther = copy(columnId = columnId + base) } }
Example 20
Source File: EventSerializerSpec.scala From kafka-journal with MIT License | 5 votes |
package akka.persistence.kafka.journal import java.io.FileOutputStream import akka.persistence.PersistentRepr import akka.persistence.serialization.Snapshot import cats.effect.{IO, Sync} import com.evolutiongaming.kafka.journal.FromBytes.implicits._ import com.evolutiongaming.kafka.journal.IOSuite._ import com.evolutiongaming.kafka.journal._ import com.evolutiongaming.kafka.journal.util.CatsHelper._ import org.scalatest.funsuite.AsyncFunSuite import org.scalatest.matchers.should.Matchers import play.api.libs.json.JsString import scodec.bits.ByteVector import TestJsonCodec.instance import cats.implicits._ import scala.util.Try class EventSerializerSpec extends AsyncFunSuite with ActorSuite with Matchers { for { (name, payloadType, payload) <- List( ("PersistentRepr.bin", PayloadType.Binary, Snapshot("binary")), ("PersistentRepr.text.json", PayloadType.Json, "text"), ("PersistentRepr.json", PayloadType.Json, JsString("json"))) } { test(s"toEvent & toPersistentRepr, payload: $payload") { val persistenceId = "persistenceId" val persistentRepr = PersistentRepr( payload = payload, sequenceNr = 1, persistenceId = persistenceId, manifest = "manifest", writerUuid = "writerUuid") val fa = for { serializer <- EventSerializer.of[IO](actorSystem) event <- serializer.toEvent(persistentRepr) actual <- serializer.toPersistentRepr(persistenceId, event) _ <- Sync[IO].delay { actual shouldEqual persistentRepr } payload <- event.payload.getOrError[IO]("Event.payload is not defined") _ = payload.payloadType shouldEqual payloadType bytes <- ByteVectorOf[IO](getClass, name) } yield { payload match { case payload: Payload.Binary => payload.value shouldEqual bytes case payload: Payload.Text => payload.value shouldEqual bytes.fromBytes[Try, String].get case payload: Payload.Json => payload.value shouldEqual JsonCodec.summon[Try].decode.fromBytes(bytes).get } } fa.run() } } def writeToFile[F[_] : Sync](bytes: ByteVector, path: String): F[Unit] = { Sync[F].delay { val os = new FileOutputStream(path) os.write(bytes.toArray) os.close() } } }
Example 21
Source File: ConsRecordToActionHeader.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.conversions import cats.data.OptionT import cats.implicits._ import com.evolutiongaming.catshelper.MonadThrowable import com.evolutiongaming.kafka.journal._ import com.evolutiongaming.kafka.journal.util.CatsHelper._ import com.evolutiongaming.skafka.Header import scodec.bits.ByteVector trait ConsRecordToActionHeader[F[_]] { def apply(consRecord: ConsRecord): OptionT[F, ActionHeader] } object ConsRecordToActionHeader { implicit def apply[F[_] : MonadThrowable](implicit fromBytes: FromBytes[F, Option[ActionHeader]] ): ConsRecordToActionHeader[F] = { consRecord: ConsRecord => { def header = consRecord .headers .find { _.key === ActionHeader.key } def actionHeader(header: Header) = { val byteVector = ByteVector.view(header.value) fromBytes(byteVector).adaptError { case e => JournalError(s"ConsRecordToActionHeader failed for $consRecord: $e", e) } } for { header <- header.toOptionT[F] actionHeader <- actionHeader(header).toOptionT } yield actionHeader } } }
Example 22
Source File: ActionToProducerRecord.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.conversions import cats.implicits._ import com.evolutiongaming.catshelper.MonadThrowable import com.evolutiongaming.kafka.journal.{Action, JournalError} import com.evolutiongaming.skafka.Header import com.evolutiongaming.skafka.producer.ProducerRecord import scodec.bits.ByteVector trait ActionToProducerRecord[F[_]] { def apply(action: Action): F[ProducerRecord[String, ByteVector]] } object ActionToProducerRecord { implicit def apply[F[_] : MonadThrowable](implicit actionHeaderToHeader: ActionHeaderToHeader[F], tupleToHeader: TupleToHeader[F] ): ActionToProducerRecord[F] = { action: Action => { val key = action.key val result = for { header <- actionHeaderToHeader(action.header) headers <- action match { case a: Action.Append => a.headers.toList.traverse { case (k, v) => tupleToHeader(k, v) } case _: Action.Mark => List.empty[Header].pure[F] case _: Action.Delete => List.empty[Header].pure[F] case _: Action.Purge => List.empty[Header].pure[F] } } yield { val payload = action match { case a: Action.Append => a.payload.some case _: Action.Mark => none case _: Action.Delete => none case _: Action.Purge => none } ProducerRecord( topic = key.topic, value = payload, key = key.id.some, timestamp = action.timestamp.some, headers = header :: headers) } result.handleErrorWith { cause => JournalError(s"ActionToProducerRecord failed for $action: $cause", cause) .raiseError[F, ProducerRecord[String, ByteVector]] } } } }
Example 23
Source File: HeaderToTuple.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.conversions import cats.implicits._ import com.evolutiongaming.catshelper.ApplicativeThrowable import com.evolutiongaming.kafka.journal.{FromBytes, JournalError} import com.evolutiongaming.skafka.Header import scodec.bits.ByteVector trait HeaderToTuple[F[_]] { def apply(header: Header): F[(String, String)] } object HeaderToTuple { implicit def apply[F[_] : ApplicativeThrowable](implicit stringFromBytes: FromBytes[F, String], ): HeaderToTuple[F] = { header: Header => { val bytes = ByteVector.view(header.value) stringFromBytes(bytes) .map { value => (header.key, value) } .adaptErr { case e => JournalError(s"HeaderToTuple failed for $header: $e", e) } } } }
Example 24
Source File: JsonCodecTest.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal import cats.implicits._ import org.scalatest.FunSuite import org.scalatest.matchers.should.Matchers import play.api.libs.json.{JsString, Json} import scodec.bits.ByteVector import scala.util.{Failure, Try} class JsonCodecTest extends FunSuite with Matchers { private val malformed = ByteVector.view(Json.toBytes(JsString("\ud83d\ude18\ud83d"))) test("JsonCodec.jsoniter") { JsonCodec.jsoniter[Try].decode.fromBytes(malformed) should matchPattern { case Failure(_: JournalError) => } } test("JsonCodec.playJson") { JsonCodec.playJson[Try].decode.fromBytes(malformed).isSuccess shouldEqual true } test("JsonCodec.default") { JsonCodec.default[Try].decode.fromBytes(malformed).isSuccess shouldEqual true } }
Example 25
Source File: PayloadSpec.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import play.api.libs.json.JsString import scodec.bits.ByteVector class PayloadSpec extends AnyFunSuite with Matchers { test("apply text") { Payload("text") shouldEqual Payload.text("text") } test("apply binary") { Payload(ByteVector.empty) shouldEqual Payload.binary(ByteVector.empty) } test("apply json") { Payload(JsString("json")) shouldEqual Payload.json(JsString("json")) } }
Example 26
Source File: EventsTest.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal import cats.data.{NonEmptyList => Nel} import cats.implicits._ import com.evolutiongaming.kafka.journal.Event._ import com.evolutiongaming.kafka.journal.util.ScodecHelper.{nelCodec, _} import org.scalatest.FunSuite import org.scalatest.matchers.should.Matchers import scodec.bits.ByteVector import scodec.{Attempt, codecs} import scala.util.Try class EventsTest extends FunSuite with Matchers { test("decode newer version") { implicit val jsonCodec = JsonCodec.jsoniter[Try] val codec = { val eventsCodec = nelCodec(codecs.listOfN(codecs.int32, codecs.variableSizeBytes(codecs.int32, Event.codecEventPayload))) val version = ByteVector.fromByte(100) (codecs.constant(version) ~> eventsCodec) .xmap[Events[Payload]](a => Events(a, PayloadMetadata.empty), _.events) } val events = Events(Nel.of(Event(SeqNr.min, payload = Payload.text("text").some)), PayloadMetadata.empty) val actual = for { bits <- codec.encode(events) result <- Events.codecEvents[Payload].decode(bits) } yield { result.value } actual shouldEqual events.pure[Attempt] } }
Example 27
Source File: EventualPayloadAndTypeSpec.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.eventual import cats.implicits._ import com.evolutiongaming.kafka.journal._ import org.scalatest.EitherValues import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import play.api.libs.json.{Json => PlayJson} import scodec.bits.ByteVector import scala.util.Try class EventualPayloadAndTypeSpec extends AnyFunSuite with Matchers with EitherValues { implicit val jsonCodec: JsonCodec[Try] = JsonCodec.default[Try] private val eventualWrite = EventualWrite.summon[Try, Payload] private val eventualRead = EventualRead.summon[Try, Payload] for { (name, payload) <- List( ("text", Payload.text("text")), ("binary", PayloadBinaryFromStr("binary")), ("json", Payload.json("json")) ) } { test(s"toEventual & fromEventual, payload: $name") { val actual = for { payloadAndType <- eventualWrite(payload) actual <- eventualRead(payloadAndType) } yield actual actual shouldBe payload.pure[Try] } } test("toEventual: binary") { val payload = PayloadBinaryFromStr("binary") val eventual = eventualWrite(payload) eventual shouldBe EventualPayloadAndType(payload.value.asRight, PayloadType.Binary).pure[Try] } test("toEventual: text") { val payload = Payload.Text("text") val eventual = eventualWrite(payload) eventual shouldBe EventualPayloadAndType("text".asLeft, PayloadType.Text).pure[Try] } test("toEventual: json") { val payload = Payload.Json(PlayJson.obj("key" -> "value")) val eventual = eventualWrite(payload) eventual shouldBe EventualPayloadAndType("""{"key":"value"}""".asLeft, PayloadType.Json).pure[Try] } test("fromEventual: returns an error for payload type binary and payload string") { val payloadAndType = EventualPayloadAndType("text".asLeft, PayloadType.Binary) val result = eventualRead(payloadAndType).toEither result.left.value shouldBe a[JournalError] result.left.value.getMessage should include("Bytes expected") } test("fromEventual: returns an error for payload type text and payload bytes") { val payloadAndType = EventualPayloadAndType(ByteVector.empty.asRight, PayloadType.Text) val result = eventualRead(payloadAndType).toEither result.left.value shouldBe a[JournalError] result.left.value.getMessage should include("String expected") } test("fromEventual: returns an error for payload type json and payload bytes") { val payloadAndType = EventualPayloadAndType(ByteVector.empty.asRight, PayloadType.Json) val result = eventualRead(payloadAndType).toEither result.left.value shouldBe a[JournalError] result.left.value.getMessage should include("String expected") } }
Example 28
Source File: ByteVectorOf.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal import cats.Monad import cats.implicits._ import com.evolutiongaming.kafka.journal.util.CatsHelper._ import com.evolutiongaming.kafka.journal.util.Fail import scodec.bits.ByteVector object ByteVectorOf { def apply[F[_] : Monad : Fail](clazz: Class[_], path: String): F[ByteVector] = { for { is <- Option(clazz.getResourceAsStream(path)).getOrError[F](s"file not found at $path") } yield { val bytes = new Array[Byte](is.available()) is.read(bytes) ByteVector.view(bytes) } } }
Example 29
Source File: PersistentBinaryToBytesSpec.scala From kafka-journal with MIT License | 5 votes |
package akka.persistence.kafka.journal import cats.implicits._ import com.evolutiongaming.kafka.journal.FromBytes.implicits._ import com.evolutiongaming.kafka.journal.ToBytes.implicits._ import com.evolutiongaming.kafka.journal.ByteVectorOf import com.evolutiongaming.serialization.SerializedMsg import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import scodec.bits.ByteVector import scala.util.{Success, Try} class PersistentBinaryToBytesSpec extends AnyFunSuite with Matchers { import PersistentBinaryToBytesSpec._ test("toBytes & fromBytes") { val expected = PersistentBinary( manifest = "persistentManifest".some, writerUuid = "writerUuid", payload = SerializedMsg( identifier = 2, manifest = "manifest", bytes = "payload".encodeStr)) def verify(bytes: ByteVector) = { val actual = bytes.fromBytes[Try, PersistentBinary] actual shouldEqual Success(expected) } verify(expected.toBytes[Try].get) verify(ByteVectorOf[Try](getClass, "PersistentBinary.bin").get) } } object PersistentBinaryToBytesSpec { implicit class StrOps(val self: String) extends AnyVal { def encodeStr: ByteVector = { ByteVector .encodeUtf8(self) .fold(throw _, identity) } } }
Example 30
Source File: Event.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal import cats._ import cats.implicits._ import scodec.bits.ByteVector import scodec.{Attempt, Codec, Err, codecs} import scala.util.Try final case class Event[A]( seqNr: SeqNr, tags: Tags = Tags.empty, payload: Option[A] = None) object Event { implicit def codecEvent[A](implicit payloadCodec: Codec[Option[A]]): Codec[Event[A]] = (SeqNr.codecSeqNr :: Tags.codecTags :: payloadCodec).as[Event[A]] implicit def codecEventPayload(implicit jsonCodec: JsonCodec[Try]): Codec[Event[Payload]] = { val codecJson: Codec[Payload.Json] = Payload.Json.codecJson implicit val payloadCodec: Codec[Option[Payload]] = { val errEmpty = Err("") def codecSome[A](implicit codec: Codec[A]) = { codec.exmap[Option[A]]( a => Attempt.successful(a.some), a => Attempt.fromOption(a, errEmpty)) } def codecOpt[A](payloadType: Byte, codec: Codec[Option[A]]) = { val byteVector = ByteVector.fromByte(payloadType) codecs.constant(byteVector) ~> codecs.variableSizeBytes(codecs.int32, codec) } val emptyCodec = codecOpt(0, codecs.provide(none[Payload])) val binaryCodec = codecOpt(1, codecSome[Payload.Binary]) val jsonCodec = codecOpt(2, codecSome[Payload.Json](codecJson)) val textCodec = codecOpt(3, codecSome[Payload.Text]) codecs.choice[Option[Payload]]( binaryCodec.upcast, jsonCodec.upcast, textCodec.upcast, emptyCodec) } codecEvent[Payload] } implicit val traverseEvent: Traverse[Event] = new Traverse[Event] { override def traverse[G[_] : Applicative, A, B](fa: Event[A])(f: A => G[B]): G[Event[B]] = fa.payload.traverse(f) .map(newPayload => fa.copy(payload = newPayload)) override def foldLeft[A, B](fa: Event[A], b: B)(f: (B, A) => B): B = fa.payload.fold(b)(a => f(b, a)) override def foldRight[A, B](fa: Event[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = fa.payload.fold(lb)(a => f(a, lb)) } }
Example 31
Source File: Instances.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.circe import java.nio.charset.StandardCharsets import cats.implicits._ import com.evolutiongaming.catshelper._ import com.evolutiongaming.kafka.journal.PayloadAndType._ import com.evolutiongaming.kafka.journal._ import com.evolutiongaming.kafka.journal.circe.Codecs._ import com.evolutiongaming.kafka.journal.conversions._ import com.evolutiongaming.kafka.journal.eventual.EventualRead import io.circe._ import io.circe.jawn._ import io.circe.syntax._ import scodec.bits.ByteVector object Instances { implicit def kafkaWrite[F[_] : MonadThrowable]( implicit payloadJsonToBytes: ToBytes[F, PayloadJson[Json]] ): KafkaWrite[F, Json] = KafkaWrite.writeJson(EventJsonPayloadAndType(_, PayloadType.Json), payloadJsonToBytes) implicit def kafkaRead[F[_] : MonadThrowable]( implicit payloadJsonFromBytes: FromBytes[F, PayloadJson[Json]] ): KafkaRead[F, Json] = KafkaRead.readJson(payloadJsonFromBytes, (json: EventJsonPayloadAndType[Json]) => json.payload.pure[F]) implicit def eventualRead[F[_] : MonadThrowable]: EventualRead[F, Json] = EventualRead.readJson(str => FromCirceResult.summon[F].apply(parse(str))) implicit def payloadJsonToBytes[F[_]: FromTry]: ToBytes[F, PayloadJson[Json]] = fromEncoder implicit def payloadJsonFromBytes[F[_]: ApplicativeThrowable]: FromBytes[F, PayloadJson[Json]] = fromDecoder private def fromEncoder[F[_] : FromTry, A : Encoder]: ToBytes[F, A] = a => FromTry[F].unsafe { val json = a.asJson val byteBuffer = Printer.noSpaces.printToByteBuffer(json, StandardCharsets.UTF_8) ByteVector.view(byteBuffer) } private def fromDecoder[F[_] : ApplicativeThrowable, A : Decoder]: FromBytes[F, A] = bytes => FromCirceResult.summon[F].apply(decodeByteBuffer[A](bytes.toByteBuffer)) .adaptErr { case e => JournalError(s"Failed to parse $bytes json: $e", e) } }
Example 32
Source File: EventualPayloadAndTypeSpec.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.circe import cats.implicits._ import com.evolutiongaming.kafka.journal.TestJsonCodec.instance import com.evolutiongaming.kafka.journal._ import com.evolutiongaming.kafka.journal.circe.Instances._ import com.evolutiongaming.kafka.journal.eventual._ import io.circe.{Json => CirceJson} import org.scalatest.EitherValues import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import play.api.libs.json.{Json => PlayJson} import scodec.bits.ByteVector import scala.util.Try class EventualPayloadAndTypeSpec extends AnyFunSuite with Matchers with EitherValues { private val playEventualWrite = EventualWrite.summon[Try, Payload] private val circeEventualRead = EventualRead.summon[Try, CirceJson] for { (playPayload, circePayload) <- List( (Payload.json(PlayJson.obj(("key", "value"))), CirceJson.obj("key" -> CirceJson.fromString("value"))) ) } { test(s"toEventual with Play, fromEventual with Circe") { val actual = for { payloadAndType <- playEventualWrite(playPayload) actual <- circeEventualRead(payloadAndType) } yield actual actual shouldBe circePayload.pure[Try] } } for { (name, payloadAndType) <- List( ("binary", EventualPayloadAndType(ByteVector.empty.asRight, PayloadType.Binary)), ("text", EventualPayloadAndType("text".asLeft, PayloadType.Text)) ) } { test(s"fromEventual: returns an error for non-json payload type: $name") { val result = circeEventualRead(payloadAndType).toEither result.left.value shouldBe a[JournalError] result.left.value.getMessage should include(payloadAndType.payloadType.toString) } } test("fromEventual: returns an error for payload type json and payload bytes") { val payloadAndType = EventualPayloadAndType(ByteVector.empty.asRight, PayloadType.Json) val result = circeEventualRead(payloadAndType).toEither result.left.value shouldBe a[JournalError] result.left.value.getMessage should include("String expected") } test("fromEventual: returns an error for malformed json") { val malformed = "{\"key\": {sss}}" val payloadAndType = EventualPayloadAndType(malformed.asLeft, PayloadType.Json) val result = circeEventualRead(payloadAndType).toEither result.left.value shouldBe a[JournalError] result.left.value.getMessage should (include("ParsingFailure") and include("sss")) } }
Example 33
Source File: Binary.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.common import java.nio.charset.Charset import java.nio.charset.StandardCharsets import cats.effect._ import fs2.{Chunk, Pipe, Stream} import scodec.bits.ByteVector final case class Binary[F[_]](name: String, mime: MimeType, data: Stream[F, Byte]) { def withMime(mime: MimeType): Binary[F] = copy(mime = mime) } object Binary { def apply[F[_]](name: String, data: Stream[F, Byte]): Binary[F] = Binary[F](name, MimeType.octetStream, data) def utf8[F[_]](name: String, content: String): Binary[F] = Binary[F]( name, MimeType.octetStream, Stream.emit(content).through(fs2.text.utf8Encode) ) def text[F[_]](name: String, content: String): Binary[F] = utf8(name, content).withMime(MimeType.plain.withUtf8Charset) def text[F[_]](name: String, content: ByteVector, cs: Charset): Binary[F] = Binary(name, MimeType.plain.withCharset(cs), Stream.chunk(Chunk.byteVector(content))) def html[F[_]](name: String, content: String): Binary[F] = utf8(name, content).withMime(MimeType.html.withUtf8Charset) def html[F[_]](name: String, content: ByteVector, cs: Charset): Binary[F] = Binary(name, MimeType.html.withCharset(cs), Stream.chunk(Chunk.byteVector(content))) def decode[F[_]](cs: Charset): Pipe[F, Byte, String] = if (cs == StandardCharsets.UTF_8) fs2.text.utf8Decode else util.decode[F](cs) def loadAllBytes[F[_]: Sync](data: Stream[F, Byte]): F[ByteVector] = data.chunks.map(_.toByteVector).compile.fold(ByteVector.empty)((r, e) => r ++ e) // This is a copy from org.http4s.util // Http4s is licensed under the Apache License 2.0 private object util { import fs2._ import java.nio._ private val utf8Bom: Chunk[Byte] = Chunk(0xef.toByte, 0xbb.toByte, 0xbf.toByte) def decode[F[_]](charset: Charset): Pipe[F, Byte, String] = { val decoder = charset.newDecoder val maxCharsPerByte = math.ceil(decoder.maxCharsPerByte().toDouble).toInt val avgBytesPerChar = math.ceil(1.0 / decoder.averageCharsPerByte().toDouble).toInt val charBufferSize = 128 _.repeatPull[String] { _.unconsN(charBufferSize * avgBytesPerChar, allowFewer = true).flatMap { case None => val charBuffer = CharBuffer.allocate(1) decoder.decode(ByteBuffer.allocate(0), charBuffer, true) decoder.flush(charBuffer) val outputString = charBuffer.flip().toString if (outputString.isEmpty) Pull.done.as(None) else Pull.output1(outputString).as(None) case Some((chunk, stream)) => if (chunk.nonEmpty) { val chunkWithoutBom = skipByteOrderMark(chunk) val bytes = chunkWithoutBom.toArray val byteBuffer = ByteBuffer.wrap(bytes) val charBuffer = CharBuffer.allocate(bytes.length * maxCharsPerByte) decoder.decode(byteBuffer, charBuffer, false) val nextStream = stream.consChunk(Chunk.byteBuffer(byteBuffer.slice())) Pull.output1(charBuffer.flip().toString).as(Some(nextStream)) } else Pull.output(Chunk.empty[String]).as(Some(stream)) } } } private def skipByteOrderMark[F[_]](chunk: Chunk[Byte]): Chunk[Byte] = if (chunk.size >= 3 && chunk.take(3) == utf8Bom) chunk.drop(3) else chunk } }
Example 34
Source File: Ident.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.common import java.security.SecureRandom import java.util.UUID import cats.Eq import cats.effect.Sync import cats.implicits._ import io.circe.{Decoder, Encoder} import scodec.bits.ByteVector case class Ident(id: String) { def isEmpty: Boolean = id.trim.isEmpty def nonEmpty: Boolean = !isEmpty def /(next: Ident): Ident = new Ident(id + "." + next.id) } object Ident { implicit val identEq: Eq[Ident] = Eq.by(_.id) val chars: Set[Char] = (('A' to 'Z') ++ ('a' to 'z') ++ ('0' to '9') ++ "-_.").toSet def randomUUID[F[_]: Sync]: F[Ident] = Sync[F].delay(unsafe(UUID.randomUUID.toString)) def randomId[F[_]: Sync]: F[Ident] = Sync[F].delay { val random = new SecureRandom() val buffer = new Array[Byte](32) random.nextBytes(buffer) unsafe(ByteVector.view(buffer).toBase58.grouped(11).mkString("-")) } def apply(str: String): Either[String, Ident] = fromString(str) def fromString(s: String): Either[String, Ident] = if (s.forall(chars.contains)) Right(new Ident(s)) else Left(s"Invalid identifier: '$s'. Allowed chars: ${chars.toList.sorted.mkString}") def fromBytes(bytes: ByteVector): Ident = unsafe(bytes.toBase58) def fromByteArray(bytes: Array[Byte]): Ident = fromBytes(ByteVector.view(bytes)) def unsafe(s: String): Ident = fromString(s) match { case Right(id) => id case Left(err) => sys.error(err) } def unapply(arg: String): Option[Ident] = fromString(arg).toOption implicit val encodeIdent: Encoder[Ident] = Encoder.encodeString.contramap(_.id) implicit val decodeIdent: Decoder[Ident] = Decoder.decodeString.emap(Ident.fromString) }
Example 35
Source File: Implicits.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.common.config import scala.reflect.ClassTag import docspell.common._ import com.github.eikek.calev.CalEvent import pureconfig._ import pureconfig.error.{CannotConvert, FailureReason} import scodec.bits.ByteVector object Implicits { implicit val lenientUriReader: ConfigReader[LenientUri] = ConfigReader[String].emap(reason(LenientUri.parse)) implicit val durationReader: ConfigReader[Duration] = ConfigReader[scala.concurrent.duration.Duration].map(sd => Duration(sd)) implicit val passwordReader: ConfigReader[Password] = ConfigReader[String].map(Password(_)) implicit val mimeTypeReader: ConfigReader[MimeType] = ConfigReader[String].emap(reason(MimeType.parse)) implicit val identReader: ConfigReader[Ident] = ConfigReader[String].emap(reason(Ident.fromString)) implicit val byteVectorReader: ConfigReader[ByteVector] = ConfigReader[String].emap(reason { str => if (str.startsWith("hex:")) ByteVector.fromHex(str.drop(4)).toRight("Invalid hex value.") else if (str.startsWith("b64:")) ByteVector.fromBase64(str.drop(4)).toRight("Invalid Base64 string.") else ByteVector .encodeUtf8(str) .left .map(ex => s"Invalid utf8 string: ${ex.getMessage}") }) implicit val caleventReader: ConfigReader[CalEvent] = ConfigReader[String].emap(reason(CalEvent.parse)) implicit val priorityReader: ConfigReader[Priority] = ConfigReader[String].emap(reason(Priority.fromString)) def reason[A: ClassTag]( f: String => Either[String, A] ): String => Either[FailureReason, A] = in => f(in).left.map(str => CannotConvert(in, implicitly[ClassTag[A]].runtimeClass.toString, str) ) }
Example 36
Source File: AuthToken.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.backend.auth import java.time.Instant import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec import cats.effect._ import cats.implicits._ import docspell.backend.Common import docspell.backend.auth.AuthToken._ import docspell.common._ import scodec.bits.ByteVector case class AuthToken(millis: Long, account: AccountId, salt: String, sig: String) { def asString = s"$millis-${b64enc(account.asString)}-$salt-$sig" def sigValid(key: ByteVector): Boolean = { val newSig = AuthToken.sign(this, key) AuthToken.constTimeEq(sig, newSig) } def sigInvalid(key: ByteVector): Boolean = !sigValid(key) def notExpired(validity: Duration): Boolean = !isExpired(validity) def isExpired(validity: Duration): Boolean = { val ends = Instant.ofEpochMilli(millis).plusMillis(validity.millis) Instant.now.isAfter(ends) } def validate(key: ByteVector, validity: Duration): Boolean = sigValid(key) && notExpired(validity) } object AuthToken { private val utf8 = java.nio.charset.StandardCharsets.UTF_8 def fromString(s: String): Either[String, AuthToken] = s.split("\\-", 4) match { case Array(ms, as, salt, sig) => for { millis <- asInt(ms).toRight("Cannot read authenticator data") acc <- b64dec(as).toRight("Cannot read authenticator data") accId <- AccountId.parse(acc) } yield AuthToken(millis, accId, salt, sig) case _ => Left("Invalid authenticator") } def user[F[_]: Sync](accountId: AccountId, key: ByteVector): F[AuthToken] = for { salt <- Common.genSaltString[F] millis = Instant.now.toEpochMilli cd = AuthToken(millis, accountId, salt, "") sig = sign(cd, key) } yield cd.copy(sig = sig) private def sign(cd: AuthToken, key: ByteVector): String = { val raw = cd.millis.toString + cd.account.asString + cd.salt val mac = Mac.getInstance("HmacSHA1") mac.init(new SecretKeySpec(key.toArray, "HmacSHA1")) ByteVector.view(mac.doFinal(raw.getBytes(utf8))).toBase64 } private def b64enc(s: String): String = ByteVector.view(s.getBytes(utf8)).toBase64 private def b64dec(s: String): Option[String] = ByteVector.fromValidBase64(s).decodeUtf8.toOption private def asInt(s: String): Option[Long] = Either.catchNonFatal(s.toLong).toOption private def constTimeEq(s1: String, s2: String): Boolean = s1.zip(s2) .foldLeft(true)({ case (r, (c1, c2)) => r & c1 == c2 }) & s1.length == s2.length }
Example 37
Source File: Login.scala From docspell with GNU General Public License v3.0 | 5 votes |
package docspell.backend.auth import cats.effect._ import cats.implicits._ import docspell.backend.auth.Login._ import docspell.common._ import docspell.store.Store import docspell.store.queries.QLogin import docspell.store.records.RUser import org.log4s._ import org.mindrot.jbcrypt.BCrypt import scodec.bits.ByteVector trait Login[F[_]] { def loginSession(config: Config)(sessionKey: String): F[Result] def loginUserPass(config: Config)(up: UserPass): F[Result] } object Login { private[this] val logger = getLogger case class Config(serverSecret: ByteVector, sessionValid: Duration) case class UserPass(user: String, pass: String) { def hidePass: UserPass = if (pass.isEmpty) copy(pass = "<none>") else copy(pass = "***") } sealed trait Result { def toEither: Either[String, AuthToken] } object Result { case class Ok(session: AuthToken) extends Result { val toEither = Right(session) } case object InvalidAuth extends Result { val toEither = Left("Authentication failed.") } case object InvalidTime extends Result { val toEither = Left("Authentication failed.") } def ok(session: AuthToken): Result = Ok(session) def invalidAuth: Result = InvalidAuth def invalidTime: Result = InvalidTime } def apply[F[_]: Effect](store: Store[F]): Resource[F, Login[F]] = Resource.pure[F, Login[F]](new Login[F] { def loginSession(config: Config)(sessionKey: String): F[Result] = AuthToken.fromString(sessionKey) match { case Right(at) => if (at.sigInvalid(config.serverSecret)) Result.invalidAuth.pure[F] else if (at.isExpired(config.sessionValid)) Result.invalidTime.pure[F] else Result.ok(at).pure[F] case Left(_) => Result.invalidAuth.pure[F] } def loginUserPass(config: Config)(up: UserPass): F[Result] = AccountId.parse(up.user) match { case Right(acc) => val okResult = store.transact(RUser.updateLogin(acc)) *> AuthToken.user(acc, config.serverSecret).map(Result.ok) for { data <- store.transact(QLogin.findUser(acc)) _ <- Sync[F].delay(logger.trace(s"Account lookup: $data")) res <- if (data.exists(check(up.pass))) okResult else Result.invalidAuth.pure[F] } yield res case Left(_) => Result.invalidAuth.pure[F] } private def check(given: String)(data: QLogin.Data): Boolean = { val collOk = data.collectiveState == CollectiveState.Active || data.collectiveState == CollectiveState.ReadOnly val userOk = data.userState == UserState.Active val passOk = BCrypt.checkpw(given, data.password.pass) collOk && userOk && passOk } }) }
Example 38
Source File: Generators.scala From eclair with Apache License 2.0 | 5 votes |
package fr.acinq.eclair.crypto import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} import fr.acinq.bitcoin.{ByteVector32, Crypto} import scodec.bits.ByteVector object Generators { def fixSize(data: ByteVector): ByteVector32 = data.length match { case 32 => ByteVector32(data) case length if length < 32 => ByteVector32(data.padLeft(32)) } def perCommitSecret(seed: ByteVector32, index: Long): PrivateKey = PrivateKey(ShaChain.shaChainFromSeed(seed, 0xFFFFFFFFFFFFL - index)) def perCommitPoint(seed: ByteVector32, index: Long): PublicKey = perCommitSecret(seed, index).publicKey def derivePrivKey(secret: PrivateKey, perCommitPoint: PublicKey): PrivateKey = { // secretkey = basepoint-secret + SHA256(per-commitment-point || basepoint) secret.add(PrivateKey(Crypto.sha256(perCommitPoint.value ++ secret.publicKey.value))) } def derivePubKey(basePoint: PublicKey, perCommitPoint: PublicKey): PublicKey = { //pubkey = basepoint + SHA256(per-commitment-point || basepoint)*G val a = PrivateKey(Crypto.sha256(perCommitPoint.value ++ basePoint.value)) basePoint.add(a.publicKey) } def revocationPubKey(basePoint: PublicKey, perCommitPoint: PublicKey): PublicKey = { val a = PrivateKey(Crypto.sha256(basePoint.value ++ perCommitPoint.value)) val b = PrivateKey(Crypto.sha256(perCommitPoint.value ++ basePoint.value)) basePoint.multiply(a).add(perCommitPoint.multiply(b)) } def revocationPrivKey(secret: PrivateKey, perCommitSecret: PrivateKey): PrivateKey = { val a = PrivateKey(Crypto.sha256(secret.publicKey.value ++ perCommitSecret.publicKey.value)) val b = PrivateKey(Crypto.sha256(perCommitSecret.publicKey.value ++ secret.publicKey.value)) secret.multiply(a).add(perCommitSecret.multiply(b)) } }
Example 39
Source File: HmacAuthMiddlewareSpec.scala From iotchain with MIT License | 5 votes |
package jbok.network.http.server.middleware import java.time.Instant import cats.Id import cats.effect.IO import cats.implicits._ import jbok.common.CommonSpec import jbok.network.http.server.authentication.HMAC import org.http4s.dsl.io._ import org.http4s.headers.Authorization import org.http4s.implicits._ import org.http4s.{AuthScheme, Credentials, Header, HttpRoutes, Request, Status, Uri} import scodec.bits.ByteVector import tsec.mac.jca.{HMACSHA256, MacSigningKey} import scala.concurrent.duration._ class HmacAuthMiddlewareSpec extends CommonSpec { "HmacAuthMiddleware" should { val key = HMACSHA256.buildKey[Id]( ByteVector.fromValidHex("70ea14ac30939a972b5a67cab952d6d7d474727b05fe7f9283abc1e505919e83").toArray ) def sign(url: String): (String, String) = { val datetime = Instant.now().toString val signature = HMAC.http.signForHeader("GET", url, datetime, key).unsafeRunSync() (signature, datetime) } val routes = HttpRoutes.of[IO] { case GET -> Root / "ping" => Ok("pong") } val service = routes.orNotFound val req = Request[IO](uri = Uri.uri("/ping")) service.run(req).unsafeRunSync().status shouldBe Status.Ok val authedService = HmacAuthMiddleware(key)(routes).orNotFound "403 if no Authorization header" in { val resp = authedService.run(req).unsafeRunSync() val text = resp.bodyAsText.compile.foldMonoid.unsafeRunSync() resp.status shouldBe Status.Forbidden text shouldBe HmacAuthError.NoAuthHeader.message } "403 if no X-Datetime header" in { val signature = HMAC.http.signForHeader("GET", "/ping", Instant.now().toString, key).unsafeRunSync() val req = Request[IO](uri = Uri.uri("/ping")).putHeaders(Authorization(Credentials.Token(AuthScheme.Bearer, signature))) val resp = authedService.run(req).unsafeRunSync() val text = resp.bodyAsText.compile.foldMonoid.unsafeRunSync() resp.status shouldBe Status.Forbidden text shouldBe HmacAuthError.NoDatetimeHeader.message } "403 if time window is closed" in { val authedService = HmacAuthMiddleware(key, 2.seconds)(routes).orNotFound val now = Instant.now() val signature = HMAC.http.signForHeader("GET", "/ping", now.toString, key).unsafeRunSync() val req = Request[IO](uri = Uri.uri("/ping")) .putHeaders( Authorization(Credentials.Token(AuthScheme.Bearer, signature)), Header("X-Datetime", now.toString) ) val resp = authedService.run(req).unsafeRunSync() resp.status shouldBe Status.Ok IO.sleep(3.seconds).unsafeRunSync() val resp2 = authedService.run(req).unsafeRunSync() val text = resp2.bodyAsText.compile.foldMonoid.unsafeRunSync() resp2.status shouldBe Status.Forbidden text shouldBe HmacAuthError.Timeout.message } "helper" in { val (sig, date) = sign("/v1/blocks") println(("Authorization", s"Bearer $sig")) println(("X-Datetime", date)) println(("Random key", ByteVector(MacSigningKey.toJavaKey[HMACSHA256](HMACSHA256.generateKey[Id]).getEncoded).toHex)) } } }
Example 40
Source File: PersonalService.scala From iotchain with MIT License | 5 votes |
package jbok.app.service import cats.effect.Sync import cats.implicits._ import jbok.common.math.N import jbok.core.api.PersonalAPI import jbok.core.config.HistoryConfig import jbok.core.keystore.KeyStore import jbok.core.ledger.History import jbok.core.models.{Address, Transaction} import jbok.core.pool.TxPool import scodec.bits.ByteVector import scala.util.Try final class PersonalService[F[_]]( historyConfig: HistoryConfig, keyStore: KeyStore[F], history: History[F], txPool: TxPool[F] )(implicit F: Sync[F]) extends PersonalAPI[F] { override def importRawKey(privateKey: ByteVector, passphrase: String): F[Address] = keyStore.importPrivateKey(privateKey, passphrase) override def newAccount(passphrase: String): F[Address] = keyStore.newAccount(passphrase) override def delAccount(address: Address): F[Boolean] = keyStore.deleteAccount(address) override def listAccounts: F[List[Address]] = keyStore.listAccounts override def sendTransaction( from: Address, passphrase: String, to: Option[Address], value: Option[N], gasLimit: Option[N], gasPrice: Option[N], nonce: Option[N], data: Option[ByteVector] ): F[ByteVector] = { val defaultGasPrice: N = 2 * N(10).pow(10) val defaultGasLimit: N = N(90000) for { wallet <- keyStore.unlockAccount(from, passphrase) pending <- txPool.getPendingTransactions latestNonceOpt = Try(pending.collect { case (stx, _) if stx.senderAddress.contains(wallet.address) => stx.nonce }.max).toOption bn <- history.getBestBlockNumber currentNonceOpt <- history.getAccount(from, bn).map(_.map(_.nonce.toN)) maybeNextTxNonce = latestNonceOpt.map(_ + 1).orElse(currentNonceOpt) tx = Transaction( nonce = nonce.getOrElse(maybeNextTxNonce.getOrElse(historyConfig.accountStartNonce)), gasPrice = gasPrice.getOrElse(defaultGasPrice), gasLimit = gasLimit.getOrElse(defaultGasLimit), receivingAddress = to, value = value.getOrElse(N(0)), payload = data.getOrElse(ByteVector.empty) ) stx <- wallet.signTx[F](tx, history.chainId) _ <- txPool.addOrUpdateTransaction(stx) } yield stx.hash } override def changePassphrase(address: Address, oldPassphrase: String, newPassphrase: String): F[Boolean] = keyStore.changePassphrase(address, oldPassphrase, newPassphrase) }
Example 41
Source File: AccountService.scala From iotchain with MIT License | 5 votes |
package jbok.app.service import cats.effect.Sync import cats.implicits._ import jbok.app.service.store.TransactionStore import jbok.common.math.N import jbok.core.config.HistoryConfig import jbok.core.ledger.History import jbok.core.models.{Account, Address, SignedTransaction} import jbok.core.pool.TxPool import jbok.core.api.{AccountAPI, BlockTag, HistoryTransaction} import scodec.bits.ByteVector final class AccountService[F[_]](config: HistoryConfig, history: History[F], txPool: TxPool[F], helper: ServiceHelper[F], txStore: TransactionStore[F])(implicit F: Sync[F]) extends AccountAPI[F] { override def getAccount(address: Address, tag: BlockTag): F[Account] = for { account <- helper.resolveAccount(address, tag) } yield account override def getCode(address: Address, tag: BlockTag): F[ByteVector] = for { block <- helper.resolveBlock(tag) world <- history.getWorldState(config.accountStartNonce, block.map(_.header.stateRoot)) code <- world.getCode(address) } yield code override def getBalance(address: Address, tag: BlockTag): F[N] = for { account <- helper.resolveAccount(address, tag) } yield account.balance.toN override def getStorageAt(address: Address, position: N, tag: BlockTag): F[ByteVector] = for { account <- helper.resolveAccount(address, tag) storage <- history.getStorage(account.storageRoot, position) } yield storage override def getTransactions(address: Address, page: Int, size: Int): F[List[HistoryTransaction]] = { val validSize = if (size < 0) 100 else 1000000.min(size) txStore.findTransactionsByAddress(address.toString, page.max(1), validSize) } override def getTransactionsByNumber(number: Int): F[List[HistoryTransaction]] = txStore.findTransactionsByNumber(number) override def getPendingTxs(address: Address): F[List[SignedTransaction]] = txPool.getPendingTransactions.map(_.keys.toList.filter(_.senderAddress.exists(_ == address))) override def getEstimatedNonce(address: Address): F[N] = for { pending <- txPool.getPendingTransactions latestNonceOpt = scala.util .Try(pending.collect { case (stx, _) if stx.senderAddress contains address => stx.nonce }.max) .toOption bn <- history.getBestBlockNumber currentNonceOpt <- history.getAccount(address, bn).map(_.map(_.nonce.toN)) defaultNonce = config.accountStartNonce.toN maybeNextTxNonce = latestNonceOpt.map(_ + 1).getOrElse(defaultNonce) max currentNonceOpt.getOrElse(defaultNonce) } yield maybeNextTxNonce }
Example 42
Source File: ContractService.scala From iotchain with MIT License | 5 votes |
package jbok.app.service import cats.effect.Sync import cats.implicits._ import jbok.common.math.N import jbok.core.ledger.{BlockExecutor, History} import jbok.core.models.{Address, Block, SignedTransaction, Transaction} import jbok.core.api.{BlockTag, CallTx, ContractAPI} import scodec.bits.ByteVector import spire.syntax.all._ import spire.compat._ final class ContractService[F[_]](history: History[F], executor: BlockExecutor[F], helper: ServiceHelper[F])(implicit F: Sync[F]) extends ContractAPI[F] { // override def getABI(address: Address): F[Option[Ast.ContractDef]] = ??? // // override def getSourceCode(address: Address): F[Option[String]] = ??? override def call(callTx: CallTx, tag: BlockTag): F[ByteVector] = for { (stx, block) <- doCall(callTx, tag) txResult <- executor.simulateTransaction(stx, callTx.from.getOrElse(Address.empty), block.header) } yield txResult.vmReturnData override def getEstimatedGas(callTx: CallTx, tag: BlockTag): F[N] = for { (stx, block) <- doCall(callTx, tag) gas <- executor.binarySearchGasEstimation(stx, callTx.from.getOrElse(Address.empty), block.header) } yield gas override def getGasPrice: F[N] = { val blockDifference = N(30) for { bestBlock <- history.getBestBlockNumber gasPrices <- List .range(bestBlock - blockDifference, bestBlock) .filter(_ >= N(0)) .traverse(history.getBlockByNumber) .map(_.flatten.flatMap(_.body.transactionList).map(_.gasPrice)) gasPrice = if (gasPrices.nonEmpty) { gasPrices.qsum / gasPrices.length } else { N(0) } } yield gasPrice } private def doCall[A](callTx: CallTx, tag: BlockTag): F[(SignedTransaction, Block)] = for { stx <- prepareTransaction(callTx, tag) blockOpt <- helper.resolveBlock(tag) block <- F.fromOption(blockOpt, new Exception()) } yield (stx, block) private def prepareTransaction(callTx: CallTx, tag: BlockTag): F[SignedTransaction] = for { gasLimit <- getGasLimit(callTx, tag) tx = Transaction(0, callTx.gasPrice, gasLimit, callTx.to, callTx.value, callTx.data) } yield SignedTransaction(tx, 0.toByte, ByteVector(0), ByteVector(0)) private def getGasLimit(callTx: CallTx, tag: BlockTag): F[N] = callTx.gas match { case Some(gas) => gas.pure[F] case None => helper.resolveBlock(tag).map(_.map(_.header.gasLimit).getOrElse(N(0))) } }
Example 43
Source File: BlockService.scala From iotchain with MIT License | 5 votes |
package jbok.app.service import cats.effect.Concurrent import cats.implicits._ import jbok.common.math.N import jbok.core.config.SyncConfig import jbok.core.ledger.History import jbok.core.models.{Block, BlockBody, BlockHeader} import jbok.core.api.BlockAPI import jbok.core.messages.Status import scodec.bits.ByteVector import spire.compat._ final class BlockService[F[_]](history: History[F], config: SyncConfig)(implicit F: Concurrent[F]) extends BlockAPI[F] { override def getStatus: F[Status] = for { genesis <- history.genesisHeader number <- history.getBestBlockNumber td <- history.getTotalDifficultyByNumber(number).map(_.getOrElse(N(0))) } yield Status(history.chainId, genesis.hash, number, td, "") override def getBestBlockNumber: F[N] = history.getBestBlockNumber override def getBlockHeaderByNumber(number: N): F[Option[BlockHeader]] = history.getBlockHeaderByNumber(number) override def getBlockHeadersByNumber(start: N, limit: Int): F[List[BlockHeader]] = { val headersCount = math.min(limit, config.maxBlockHeadersPerRequest) val range = List.range(start, start + headersCount) range.traverse(history.getBlockHeaderByNumber).map(_.flatten) } override def getBlockHeaderByHash(hash: ByteVector): F[Option[BlockHeader]] = history.getBlockHeaderByHash(hash) override def getBlockBodyByHash(hash: ByteVector): F[Option[BlockBody]] = history.getBlockBodyByHash(hash) override def getBlockBodies(hashes: List[ByteVector]): F[List[BlockBody]] = hashes .take(config.maxBlockBodiesPerRequest) .traverse(hash => history.getBlockBodyByHash(hash)) .map(_.flatten) override def getBlockByNumber(number: N): F[Option[Block]] = history.getBlockByNumber(number) override def getBlockByHash(hash: ByteVector): F[Option[Block]] = history.getBlockByHash(hash) override def getTransactionCountByHash(hash: ByteVector): F[Option[Int]] = history.getBlockBodyByHash(hash).map(_.map(_.transactionList.length)) override def getTotalDifficultyByNumber(number: N): F[Option[N]] = history.getTotalDifficultyByNumber(number) override def getTotalDifficultyByHash(hash: ByteVector): F[Option[N]] = history.getTotalDifficultyByHash(hash) }
Example 44
Source File: TransactionService.scala From iotchain with MIT License | 5 votes |
package jbok.app.service import cats.data.OptionT import cats.effect.Sync import cats.implicits._ import jbok.codec.rlp.RlpEncoded import jbok.core.ledger.History import jbok.core.models.{Receipt, SignedTransaction} import jbok.core.pool.TxPool import jbok.core.api.{BlockTag, TransactionAPI} import scodec.bits.ByteVector final class TransactionService[F[_]](history: History[F], txPool: TxPool[F], helper: ServiceHelper[F])(implicit F: Sync[F]) extends TransactionAPI[F] { override def getTx(hash: ByteVector): F[Option[SignedTransaction]] = (for { loc <- OptionT(history.getTransactionLocation(hash)) block <- OptionT(history.getBlockByHash(loc.blockHash)) stx <- OptionT.fromOption[F](block.body.transactionList.lift(loc.txIndex)) } yield stx).value override def getPendingTx(hash: ByteVector): F[Option[SignedTransaction]] = txPool.getPendingTransactions.map(_.keys.toList.find(_.hash == hash)) override def getReceipt(hash: ByteVector): F[Option[Receipt]] = (for { loc <- OptionT(history.getTransactionLocation(hash)) block <- OptionT(history.getBlockByHash(loc.blockHash)) _ <- OptionT.fromOption[F](block.body.transactionList.lift(loc.txIndex)) receipts <- OptionT(history.getReceiptsByHash(loc.blockHash)) receipt <- OptionT.fromOption[F](receipts.lift(loc.txIndex)) } yield receipt).value override def getTxByBlockHashAndIndex(hash: ByteVector, index: Int): F[Option[SignedTransaction]] = (for { block <- OptionT(history.getBlockByHash(hash)) stx <- OptionT.fromOption[F](block.body.transactionList.lift(index)) } yield stx).value override def getTxByBlockTagAndIndex(tag: BlockTag, index: Int): F[Option[SignedTransaction]] = (for { block <- OptionT(helper.resolveBlock(tag)) stx <- OptionT.fromOption[F](block.body.transactionList.lift(index)) } yield stx).value override def sendTx(stx: SignedTransaction): F[ByteVector] = txPool.addOrUpdateTransaction(stx).as(stx.hash) override def sendRawTx(data: RlpEncoded): F[ByteVector] = for { stx <- F.fromEither(data.decoded[SignedTransaction]) _ <- txPool.addOrUpdateTransaction(stx) } yield stx.hash }
Example 45
Source File: DoobieBlockStore.scala From iotchain with MIT License | 5 votes |
package jbok.app.service.store.doobie import cats.effect.Sync import cats.implicits._ import doobie.implicits._ import doobie.util.transactor.Transactor import jbok.app.service.store.BlockStore import jbok.common.math.N import scodec.bits.ByteVector final class DoobieBlockStore[F[_]](xa: Transactor[F])(implicit F: Sync[F]) extends BlockStore[F] with DoobieSupport { override def getBestBlockNumber: F[Option[N]] = sql""" SELECT blockNumber FROM blocks ORDER BY blockNumber DESC LIMIT 1 """ .query[N] .option .transact(xa) override def getBestBlockNumberAndHash: F[(N, ByteVector)] = sql""" SELECT blockNumber, blockHash FROM blocks ORDER BY blockNumber DESC LIMIT 1 """ .query[(N, ByteVector)] .unique .transact(xa) override def getBlockHashByNumber(number: N): F[Option[ByteVector]] = sql""" SELECT blockHash FROM blocks WHERE blockNumber = $number """ .query[ByteVector] .option .transact(xa) override def delByBlockNumber(number: N): F[Unit] = sql""" DELETE FROM blocks where blockNumber = $number """.update.run .transact(xa) .void override def insert(number: N, hash: ByteVector): F[Unit] = sql""" INSERT INTO blocks (blockNumber, blockHash) VALUES ($number, $hash) """.update.run.void.transact(xa) }
Example 46
Source File: TransactionAPISpec.scala From iotchain with MIT License | 5 votes |
package jbok.app.service import cats.effect.IO import jbok.app.AppSpec import jbok.core.StatefulGen import jbok.core.api.{BlockTag, TransactionAPI} import jbok.core.ledger.History import jbok.core.mining.BlockMiner import jbok.core.models.{Address, SignedTransaction, Transaction} import scodec.bits.ByteVector class TransactionAPISpec extends AppSpec { "TransactionAPI" should { "return tx by hash & number" in check { objects => val history = objects.get[History[IO]] val miner = objects.get[BlockMiner[IO]] val transaction = objects.get[TransactionAPI[IO]] val txs = random(StatefulGen.transactions(10, 10)) val stx = txs.head for { parent <- history.getBestBlock _ <- transaction.sendTx(stx) res <- transaction.getTx(stx.hash) _ = res shouldBe None res <- transaction.getPendingTx(stx.hash) _ = res shouldBe Some(stx) minedBlock <- miner.mine() res <- transaction.getTx(stx.hash) _ = res shouldBe Some(stx) res <- transaction.getPendingTx(stx.hash) _ = res shouldBe None res <- transaction.getReceipt(stx.hash).map(_.nonEmpty) _ = res shouldBe true res <- transaction.getTxByBlockHashAndIndex(minedBlock.block.header.hash, 0) _ = res shouldBe Some(stx) res <- transaction getTxByBlockTagAndIndex (BlockTag(1), 0) _ = res shouldBe Some(stx) res <- transaction.getTxByBlockTagAndIndex(BlockTag.latest, 0) _ = res shouldBe Some(stx) res <- transaction.getTxByBlockTagAndIndex(BlockTag(2), 0) _ = res shouldBe None } yield () } "return tx by hash & number send a bad stx" in check { objects => val miner = objects.get[BlockMiner[IO]] val transaction = objects.get[TransactionAPI[IO]] val tx = Transaction(1, 1, 21000, Some(Address.empty), 100000, ByteVector.empty) for { stx <- SignedTransaction.sign[IO](tx, testKeyPair, chainId) _ <- transaction.sendTx(stx) res <- transaction.getTx(stx.hash) _ = res shouldBe None res <- transaction.getPendingTx(stx.hash) _ = res shouldBe Some(stx) _ <- miner.mine() res <- transaction.getTx(stx.hash) _ = res shouldBe None res <- transaction.getPendingTx(stx.hash).map(_.isEmpty) _ = res shouldBe false res <- transaction.getReceipt(stx.hash).map(_.isEmpty) _ = res shouldBe true } yield () } "sendTx" in check { objects => val history = objects.get[History[IO]] val miner = objects.get[BlockMiner[IO]] val transaction = objects.get[TransactionAPI[IO]] val stx = random(StatefulGen.transactions(1, 1)).head for { res <- transaction.sendTx(stx) _ = res shouldBe stx.hash _ <- miner.mine() res <- history.getBestBlock.map(_.body.transactionList.head) _ = res shouldBe stx } yield () } "sendRawTx" in check { objects => val history = objects.get[History[IO]] val miner = objects.get[BlockMiner[IO]] val transaction = objects.get[TransactionAPI[IO]] val stx = random(StatefulGen.transactions(1, 1)).head for { res <- transaction.sendRawTx(stx.bytes) _ = res shouldBe stx.hash _ <- miner.mine() res <- history.getBestBlock.map(_.body.transactionList.head) _ = res shouldBe stx } yield () } } }
Example 47
Source File: ContractAPISpec.scala From iotchain with MIT License | 5 votes |
package jbok.app.service import cats.effect.IO import cats.implicits._ import jbok.app.AppSpec import jbok.common.math.N import jbok.core.api.{CallTx, ContractAPI} import jbok.core.mining.BlockMiner import scodec.bits.ByteVector class ContractAPISpec extends AppSpec { "ContractAPI" should { "return gasPrice" in { List(15, 45).foreach { blockN => check { objects => val miner = objects.get[BlockMiner[IO]] val contract = objects.get[ContractAPI[IO]] for { _ <- miner.mineN(blockN) res <- contract.getGasPrice _ = res shouldBe N(0) } yield () } } } "call transaction" in check { objects => val contract = objects.get[ContractAPI[IO]] val callTx = CallTx( from = None, to = None, gas = None, gasPrice = 0, value = 0, data = ByteVector.fromValidHex( "60806040526040805190810160405280600c81526020017f494f54206f6e20436861696e000000000000000000000000000000000000000081525060009080519060200190620000519291906200010e565b506040805190810160405280600381526020017f4954430000000000000000000000000000000000000000000000000000000000815250600190805190602001906200009f9291906200010e565b506012600255600254600a0a6305f5e10002600355348015620000c157600080fd5b50600354600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550620001bd565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200015157805160ff191683800117855562000182565b8280016001018555821562000182579182015b828111156200018157825182559160200191906001019062000164565b5b50905062000191919062000195565b5090565b620001ba91905b80821115620001b65760008160009055506001016200019c565b5090565b90565b6110c080620001cd6000396000f3006080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014f57806318160ddd146101b457806323b872dd146101df578063313ce5671461026457806342966c681461028f57806370a08231146102d457806379cc67901461032b57806395d89b4114610390578063a9059cbb14610420578063cae9ca511461046d578063dd62ed3e14610518575b600080fd5b3480156100cb57600080fd5b506100d461058f565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101145780820151818401526020810190506100f9565b50505050905090810190601f1680156101415780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015b57600080fd5b5061019a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061062d565b604051808215151515815260200191505060405180910390f35b3480156101c057600080fd5b506101c96106ba565b6040518082815260200191505060405180910390f35b3480156101eb57600080fd5b5061024a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106c0565b604051808215151515815260200191505060405180910390f35b34801561027057600080fd5b506102796107ed565b6040518082815260200191505060405180910390f35b34801561029b57600080fd5b506102ba600480360381019080803590602001909291905050506107f3565b604051808215151515815260200191505060405180910390f35b3480156102e057600080fd5b50610315600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f7565b6040518082815260200191505060405180910390f35b34801561033757600080fd5b50610376600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061090f565b604051808215151515815260200191505060405180910390f35b34801561039c57600080fd5b506103a5610b29565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103e55780820151818401526020810190506103ca565b50505050905090810190601f1680156104125780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561042c57600080fd5b5061046b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610bc7565b005b34801561047957600080fd5b506104fe600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610bd6565b604051808215151515815260200191505060405180910390f35b34801561052457600080fd5b50610579600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d59565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106255780601f106105fa57610100808354040283529160200191610625565b820191906000526020600020905b81548152906001019060200180831161060857829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60035481565b6000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561074d57600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506107e2848484610d7e565b600190509392505050565b60025481565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561084357600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b60046020528060005260406000206000915090505481565b600081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561095f57600080fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111515156109ea57600080fd5b81600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bbf5780601f10610b9457610100808354040283529160200191610bbf565b820191906000526020600020905b815481529060010190602001808311610ba257829003601f168201915b505050505081565b610bd2338383610d7e565b5050565b600080849050610be6858561062d565b15610d50578073ffffffffffffffffffffffffffffffffffffffff16638f4ffcb1338630876040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610ce0578082015181840152602081019050610cc5565b50505050905090810190601f168015610d0d5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b5050505060019150610d51565b5b509392505050565b6005602052816000526040600020602052806000526040600020600091509150505481565b6000808373ffffffffffffffffffffffffffffffffffffffff1614151515610da557600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610df357600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401111515610e8157600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401905081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a380600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540114151561108e57fe5b505050505600a165627a7a7230582012e3b4c1ec46ba19f4ea45d28ee4b34b34393f066d96bfc404b036b13c8d0f1b0029") ) for { res <- contract.call(callTx) _ = res shouldBe ByteVector.fromValidHex( "0x6080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014f57806318160ddd146101b457806323b872dd146101df578063313ce5671461026457806342966c681461028f57806370a08231146102d457806379cc67901461032b57806395d89b4114610390578063a9059cbb14610420578063cae9ca511461046d578063dd62ed3e14610518575b600080fd5b3480156100cb57600080fd5b506100d461058f565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101145780820151818401526020810190506100f9565b50505050905090810190601f1680156101415780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015b57600080fd5b5061019a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061062d565b604051808215151515815260200191505060405180910390f35b3480156101c057600080fd5b506101c96106ba565b6040518082815260200191505060405180910390f35b3480156101eb57600080fd5b5061024a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106c0565b604051808215151515815260200191505060405180910390f35b34801561027057600080fd5b506102796107ed565b6040518082815260200191505060405180910390f35b34801561029b57600080fd5b506102ba600480360381019080803590602001909291905050506107f3565b604051808215151515815260200191505060405180910390f35b3480156102e057600080fd5b50610315600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f7565b6040518082815260200191505060405180910390f35b34801561033757600080fd5b50610376600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061090f565b604051808215151515815260200191505060405180910390f35b34801561039c57600080fd5b506103a5610b29565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103e55780820151818401526020810190506103ca565b50505050905090810190601f1680156104125780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561042c57600080fd5b5061046b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610bc7565b005b34801561047957600080fd5b506104fe600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610bd6565b604051808215151515815260200191505060405180910390f35b34801561052457600080fd5b50610579600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d59565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106255780601f106105fa57610100808354040283529160200191610625565b820191906000526020600020905b81548152906001019060200180831161060857829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60035481565b6000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561074d57600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506107e2848484610d7e565b600190509392505050565b60025481565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561084357600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b60046020528060005260406000206000915090505481565b600081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561095f57600080fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111515156109ea57600080fd5b81600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bbf5780601f10610b9457610100808354040283529160200191610bbf565b820191906000526020600020905b815481529060010190602001808311610ba257829003601f168201915b505050505081565b610bd2338383610d7e565b5050565b600080849050610be6858561062d565b15610d50578073ffffffffffffffffffffffffffffffffffffffff16638f4ffcb1338630876040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610ce0578082015181840152602081019050610cc5565b50505050905090810190601f168015610d0d5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b5050505060019150610d51565b5b509392505050565b6005602052816000526040600020602052806000526040600020600091509150505481565b6000808373ffffffffffffffffffffffffffffffffffffffff1614151515610da557600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610df357600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401111515610e8157600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401905081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a380600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540114151561108e57fe5b505050505600a165627a7a7230582012e3b4c1ec46ba19f4ea45d28ee4b34b34393f066d96bfc404b036b13c8d0f1b0029") } yield () } "getEstimatedGas" in check { objects => val contract = objects.get[ContractAPI[IO]] val callTx = CallTx( from = None, to = None, gas = None, gasPrice = 0, value = 0, data = ByteVector.fromValidHex( "60806040526040805190810160405280600c81526020017f494f54206f6e20436861696e000000000000000000000000000000000000000081525060009080519060200190620000519291906200010e565b506040805190810160405280600381526020017f4954430000000000000000000000000000000000000000000000000000000000815250600190805190602001906200009f9291906200010e565b506012600255600254600a0a6305f5e10002600355348015620000c157600080fd5b50600354600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550620001bd565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200015157805160ff191683800117855562000182565b8280016001018555821562000182579182015b828111156200018157825182559160200191906001019062000164565b5b50905062000191919062000195565b5090565b620001ba91905b80821115620001b65760008160009055506001016200019c565b5090565b90565b6110c080620001cd6000396000f3006080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014f57806318160ddd146101b457806323b872dd146101df578063313ce5671461026457806342966c681461028f57806370a08231146102d457806379cc67901461032b57806395d89b4114610390578063a9059cbb14610420578063cae9ca511461046d578063dd62ed3e14610518575b600080fd5b3480156100cb57600080fd5b506100d461058f565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101145780820151818401526020810190506100f9565b50505050905090810190601f1680156101415780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015b57600080fd5b5061019a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061062d565b604051808215151515815260200191505060405180910390f35b3480156101c057600080fd5b506101c96106ba565b6040518082815260200191505060405180910390f35b3480156101eb57600080fd5b5061024a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106c0565b604051808215151515815260200191505060405180910390f35b34801561027057600080fd5b506102796107ed565b6040518082815260200191505060405180910390f35b34801561029b57600080fd5b506102ba600480360381019080803590602001909291905050506107f3565b604051808215151515815260200191505060405180910390f35b3480156102e057600080fd5b50610315600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f7565b6040518082815260200191505060405180910390f35b34801561033757600080fd5b50610376600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061090f565b604051808215151515815260200191505060405180910390f35b34801561039c57600080fd5b506103a5610b29565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103e55780820151818401526020810190506103ca565b50505050905090810190601f1680156104125780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561042c57600080fd5b5061046b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610bc7565b005b34801561047957600080fd5b506104fe600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610bd6565b604051808215151515815260200191505060405180910390f35b34801561052457600080fd5b50610579600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d59565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106255780601f106105fa57610100808354040283529160200191610625565b820191906000526020600020905b81548152906001019060200180831161060857829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60035481565b6000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561074d57600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506107e2848484610d7e565b600190509392505050565b60025481565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561084357600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b60046020528060005260406000206000915090505481565b600081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561095f57600080fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111515156109ea57600080fd5b81600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816003600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bbf5780601f10610b9457610100808354040283529160200191610bbf565b820191906000526020600020905b815481529060010190602001808311610ba257829003601f168201915b505050505081565b610bd2338383610d7e565b5050565b600080849050610be6858561062d565b15610d50578073ffffffffffffffffffffffffffffffffffffffff16638f4ffcb1338630876040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610ce0578082015181840152602081019050610cc5565b50505050905090810190601f168015610d0d5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b5050505060019150610d51565b5b509392505050565b6005602052816000526040600020602052806000526040600020600091509150505481565b6000808373ffffffffffffffffffffffffffffffffffffffff1614151515610da557600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610df357600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401111515610e8157600080fd5b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401905081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a380600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540114151561108e57fe5b505050505600a165627a7a7230582012e3b4c1ec46ba19f4ea45d28ee4b34b34393f066d96bfc404b036b13c8d0f1b0029") ) contract.getEstimatedGas(callTx).map(_ shouldBe N(1319766)).void } } }
Example 48
Source File: BlockView.scala From iotchain with MIT License | 5 votes |
package jbok.app.views import com.thoughtworks.binding import com.thoughtworks.binding.Binding import com.thoughtworks.binding.Binding.Var import jbok.app.AppState import jbok.app.components.{TabPane, Tabs} import jbok.core.api.HistoryTransaction import jbok.core.models._ import org.scalajs.dom._ import scodec.bits.ByteVector import scala.scalajs.js.Date final case class BlockView(state: AppState, block: Block) { val stxs: Var[List[HistoryTransaction]] = Var(List.empty) val stxsView = StxsView(state, stxs) private def fetch() = { val nodeId = state.activeNode.value.getOrElse("") val client = state.clients.value.get(nodeId) client.foreach { jbokClient => val p = for { txs <- jbokClient.account.getTransactionsByNumber(block.header.number.toInt) _ = stxs.value = txs } yield () p.unsafeToFuture() } } fetch() @binding.dom val overview: Binding[Element] = <div> <table class="table-view"> { val header = block.header val size = block.body.transactionList.size <tr> <th>Height:</th> <td>{header.number.toString}</td> </tr> <tr> <th>TimeStamp:</th> <td>{new Date(header.unixTimestamp).toDateString()}</td> </tr> <tr> <th>Transactions:</th> <td>{s"${size.toLong} transactions in this Block"}</td> </tr> <tr> <th>This Block Hash:</th> <td>{header.hash.toHex}</td> </tr> <tr> <th>Parent Hash:</th> <td><a onclick={(e: Event) => state.searchBlockHash(header.parentHash.toHex)}>{header.parentHash.toHex}</a></td> </tr> <tr> <th>Mined By:</th> <td>{header.beneficiary.toHex}</td> </tr> <tr> <th>Difficulty:</th> <td>{header.difficulty.toString}</td> </tr> <tr> <th>Gas Used:</th> <td>{header.gasUsed.toString}</td> </tr> <tr> <th>Gas Limit:</th> <td>{header.gasLimit.toString}</td> </tr> <tr> <th>Extra Data:</th> <td>{header.extra.bytes.toHex}</td> </tr> } </table> </div> @binding.dom val txsView: Binding[Element] = <div> {stxsView.render.bind} </div> val tabView = Tabs( List(TabPane("Overview", overview), TabPane("Transactions", txsView)), className = "tab-small" ) @binding.dom def render: Binding[Element] = <div> {tabView.render.bind} </div> }
Example 49
Source File: RegisterView.scala From iotchain with MIT License | 5 votes |
package jbok.app.views import cats.implicits._ import com.thoughtworks.binding import com.thoughtworks.binding.Binding import com.thoughtworks.binding.Binding.Var import fastparse.Parsed.Failure import jbok.app.{AppState, Contract} import jbok.app.components.{Input, Notification} import jbok.app.helper.InputValidator import jbok.core.models.Address import jbok.evm.solidity.SolidityParser import org.scalajs.dom.{Element, Event} import scodec.bits.ByteVector final case class RegisterView(state: AppState) { val currentId = state.activeNode.value val contractAddress = Input("Address", "address", validator = InputValidator.isValidAddress) val contractCode = Input( "Code", """pragma solidity ^0.4.0; | |contract SimpleStorage { | uint storedData; | | function set(uint x) public { | storedData = x; | } | | function get() public view returns (uint) { | return storedData; | } |} """.stripMargin, `type` = "textarea" ) val statusMessage: Var[Option[String]] = Var(None) def checkAndGenerateInput() = { statusMessage.value = None for { address <- if (contractAddress.isValid) Right(contractAddress.value) else Left("not valid contract address.") code <- if (contractCode.isValid) Right(contractCode.value) else Left("not valid contract code.") } yield _submit(address, code) } def _submit(address: String, code: String) = { val parseResult = SolidityParser.parseSource(code) val contractAddress = Address(ByteVector.fromValidHex(address)) parseResult.fold( (s, i, e) => { val msg = s match { case "" => "Position " + e.input.prettyIndex(i) + ", found " + Failure.formatTrailing(e.input, i) case s => Failure.formatMsg(e.input, List(s -> i), i) } statusMessage.value = Some(s"parse error: ${msg}") }, (r, i) => currentId.foreach(id => { state.nodes.value.get(id).foreach(_.contractsABI.value += contractAddress -> Contract(contractAddress, r.ABI.last.methods)) statusMessage.value = Some("register success.") }) ) } val registerOnClick = (_: Event) => checkAndGenerateInput().leftMap(error => statusMessage.value = Some(error)) @binding.dom def render: Binding[Element] = <div> <div> <label for="address"><b>Address</b></label> {contractAddress.render.bind} </div> <div> <label for="code"><b>Address</b></label> {contractCode.render.bind} </div> { val onclose = (_: Event) => statusMessage.value = None @binding.dom def content(status: String):Binding[Element] = <div style="padding-left: 10px">{status}</div> statusMessage.bind match { case None => <div/> case Some(status) if status =="register success." => Notification.renderSuccess(content(status), onclose).bind case Some(status) => Notification.renderWarning(content(status), onclose).bind } } <div> <button id="register-contract" onclick={registerOnClick} style={"width: 100%"} >register</button> </div> </div> }
Example 50
Source File: BouncyHash.scala From iotchain with MIT License | 5 votes |
package jbok.crypto.hash import java.security.{MessageDigest, Security} import org.bouncycastle.jcajce.provider.digest.Keccak import org.bouncycastle.jce.provider.BouncyCastleProvider import scodec.bits.ByteVector object BouncyHash { if (Security.getProvider("BC") == null) { Security.addProvider(new BouncyCastleProvider()) } def genInstance(algorithm: String): MessageDigest = MessageDigest.getInstance(algorithm, "BC") val sha256 = genInstance("SHA-256") val ripemd160 = genInstance("RipeMD160") def kec256(bytes: ByteVector) = new Keccak.Digest256().digest(bytes.toArray) def kec512(bytes: ByteVector) = new Keccak.Digest512().digest(bytes.toArray) }
Example 51
Source File: CryptoHasherPlatform.scala From iotchain with MIT License | 5 votes |
package jbok.crypto.hash import scodec.bits.ByteVector trait CryptoHasherPlatform { implicit val kec256Platform: CryptoHasher[Keccak256] = new CryptoHasher[Keccak256] { override def hash(bytes: ByteVector): ByteVector = ByteVector(BouncyHash.kec256(bytes)) } implicit val kec512Platform: CryptoHasher[Keccak512] = new CryptoHasher[Keccak512] { override def hash(bytes: ByteVector): ByteVector = ByteVector(BouncyHash.kec512(bytes)) } implicit val sha256Platform: CryptoHasher[SHA256] = new CryptoHasher[SHA256] { override def hash(bytes: ByteVector): ByteVector = ByteVector(BouncyHash.sha256.digest(bytes.toArray)) } implicit val ripemd160Platform: CryptoHasher[RipeMD160] = new CryptoHasher[RipeMD160] { override def hash(bytes: ByteVector): ByteVector = ByteVector(BouncyHash.ripemd160.digest(bytes.toArray)) } }
Example 52
Source File: SCryptSpec.scala From iotchain with MIT License | 5 votes |
package jbok.crypto import java.nio.charset.StandardCharsets import jbok.common.CommonSpec import jbok.crypto.password._ import scodec.bits.ByteVector class SCryptSpec extends CommonSpec { "SCrypt" should { "correctly evaluate for the test vectors" in { // https://datatracker.ietf.org/doc/rfc7914/?include_text=1 val testVectors = Table[String, String, Int, Int, Int, Int, String]( ("passphrase", "salt", "n", "r", "p", "dklen", "derivedKey"), ("", "", 16, 1, 1, 64, "77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906"), ("password", "NaCl", 1024, 8, 16, 64, "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640"), // takes a bit too long to be run on the CI // leaving this around as it's a valid test if we want to examine this function in the future // ("pleaseletmein", "SodiumChloride", 1048576, 8, 1, 64, // "2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4"), ("pleaseletmein", "SodiumChloride", 16384, 8, 1, 64, "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887") ) forAll(testVectors) { case (pass, s, n, r, p, dklen, dk) => val salt = ByteVector(s.getBytes(StandardCharsets.US_ASCII)) val derivedKey = ByteVector.fromValidHex(dk) SCrypt.derive(pass, salt, n, r, p, dklen) shouldBe derivedKey } } } }
Example 53
Source File: CryptoHasher.scala From iotchain with MIT License | 5 votes |
package jbok.crypto.hash import scodec.bits.ByteVector sealed trait Keccak256 sealed trait Keccak512 sealed trait SHA256 sealed trait RipeMD160 trait CryptoHasher[A] { def hash(bytes: ByteVector): ByteVector } object CryptoHasher { def apply[A](implicit ev: CryptoHasher[A]): CryptoHasher[A] = ev }
Example 54
Source File: KeyPair.scala From iotchain with MIT License | 5 votes |
package jbok.crypto.signature import java.math.BigInteger import cats.effect.IO import jbok.codec.json.implicits._ import io.circe.generic.extras.ConfiguredJsonCodec import scodec.bits.ByteVector @ConfiguredJsonCodec final case class KeyPair(public: KeyPair.Public, secret: KeyPair.Secret) object KeyPair { @ConfiguredJsonCodec final case class Public(bytes: ByteVector) extends AnyVal object Public { def apply(hex: String): Public = Public(ByteVector.fromValidHex(hex)) def apply(bytes: Array[Byte]): Public = Public(ByteVector(bytes)) } @ConfiguredJsonCodec final case class Secret(bytes: ByteVector) extends AnyVal { def d: BigInteger = new BigInteger(1, bytes.toArray) } object Secret { def apply(d: BigInteger): Secret = apply(ByteVector(d.toByteArray)) def apply(hex: String): Secret = apply(ByteVector.fromValidHex(hex)) def apply(bytes: Array[Byte]): Secret = apply(ByteVector(bytes)) def apply(bv: ByteVector): Secret = new Secret(bv.takeRight(32).padLeft(32)) } def fromSecret(secret: ByteVector): KeyPair = { val sec = KeyPair.Secret(secret) val pub = Signature[ECDSA].generatePublicKey[IO](sec).unsafeRunSync() KeyPair(pub, sec) } }
Example 55
Source File: CryptoSignature.scala From iotchain with MIT License | 5 votes |
package jbok.crypto.signature import io.circe.generic.extras.ConfiguredJsonCodec import jbok.codec.json.implicits._ import scodec.bits.ByteVector @ConfiguredJsonCodec final case class CryptoSignature(r: BigInt, s: BigInt, v: BigInt) { def bytes: Array[Byte] = CryptoSignature.unsignedPadding(r) ++ CryptoSignature.unsignedPadding(s) ++ CryptoSignature.unsigned(v) } object CryptoSignature { def unsigned(bigInteger: BigInt): Array[Byte] = { val asByteArray = bigInteger.toByteArray if (asByteArray.head == 0) asByteArray.tail else asByteArray } def unsignedPadding(bigInt: BigInt): Array[Byte] = { val bytes = unsigned(bigInt) ByteVector(bytes).take(32).padLeft(32).toArray } def apply(bytes: Array[Byte]): CryptoSignature = { require(bytes.length >= 65, s"signature length should be 65 instead of ${bytes.length}") CryptoSignature( BigInt(1, bytes.slice(0, 32)), BigInt(1, bytes.slice(32, 64)), BigInt(1, bytes.slice(64, bytes.length)) ) } def apply(r: ByteVector, s: ByteVector, v: ByteVector): CryptoSignature = CryptoSignature(BigInt(1, r.toArray), BigInt(1, s.toArray), BigInt(1, v.toArray)) }
Example 56
Source File: package.scala From iotchain with MIT License | 5 votes |
package jbok import java.nio.charset.StandardCharsets import java.util.Random import jbok.crypto.hash._ import scodec.bits.ByteVector import jbok.crypto.signature.SignatureInstances trait StringSyntax { implicit final def stringSyntax(a: String): StringOps = new StringOps(a) } final class StringOps(val a : String) extends AnyVal { def utf8bytes: ByteVector = ByteVector(a.getBytes(StandardCharsets.UTF_8)) } trait CryptoSyntax extends CryptoHasherSyntax with StringSyntax trait CryptoInstances extends CryptoHasherInstances with SignatureInstances package object crypto extends CryptoSyntax with CryptoInstances { def randomByteString(random: Random, length: Int): ByteVector = ByteVector(randomByteArray(random, length)) def randomByteArray(random: Random, length: Int): Array[Byte] = { val bytes = Array.ofDim[Byte](length) random.nextBytes(bytes) bytes } }
Example 57
Source File: CryptoHasherPlatform.scala From iotchain with MIT License | 5 votes |
package jbok.crypto.hash import jbok.crypto.facade.CryptoJs import scodec.bits.ByteVector import scala.scalajs.js trait CryptoHasherPlatform { implicit val kec256Platform: CryptoHasher[Keccak256] = new CryptoHasher[Keccak256] { override def hash(bytes: ByteVector): ByteVector = { val bin = CryptoJs.sha3(CryptoJs.Hex.parse(bytes.toHex), js.Dynamic.literal(outputLength = 256)) val hex = CryptoJs.Hex.stringify(bin) ByteVector.fromValidHex(hex) } } implicit val kec512Platform: CryptoHasher[Keccak512] = new CryptoHasher[Keccak512] { override def hash(bytes: ByteVector): ByteVector = { val bin = CryptoJs.sha3(CryptoJs.Hex.parse(bytes.toHex), js.Dynamic.literal(outputLength = 512)) val hex = CryptoJs.Hex.stringify(bin) ByteVector.fromValidHex(hex) } } implicit val sha256Platform: CryptoHasher[SHA256] = new CryptoHasher[SHA256] { override def hash(bytes: ByteVector): ByteVector = { val bin = CryptoJs.sha256(CryptoJs.Hex.parse(bytes.toHex)) val hex = CryptoJs.Hex.stringify(bin) ByteVector.fromValidHex(hex) } } implicit val ripemd160Platform: CryptoHasher[RipeMD160] = new CryptoHasher[RipeMD160] { override def hash(bytes: ByteVector): ByteVector = { val bin = CryptoJs.ripemd160(CryptoJs.Hex.parse(bytes.toHex)) val hex = CryptoJs.Hex.stringify(bin) ByteVector.fromValidHex(hex) } } }
Example 58
Source File: testkit.scala From iotchain with MIT License | 5 votes |
package jbok.codec import jbok.codec.rlp.RlpCodec import jbok.codec.rlp.implicits._ import org.scalatest.{Assertion, Matchers} import scodec.bits.{BitVector, ByteVector} import scodec.{Attempt, DecodeResult, Err} object testkit extends testkit trait testkit extends Matchers { def roundtripAndMatch[A](a: A, expected: ByteVector)(implicit c: RlpCodec[A]): Assertion = { roundtrip[A](a) a.encoded.bits.bytes shouldBe expected } def roundtripLen[A](a: A, expectedNumBytes: Int)(implicit c: RlpCodec[A]): Assertion = { roundtrip[A](a) a.encoded.bits.bytes.length shouldBe expectedNumBytes } def roundtrip[A](a: A)(implicit c: RlpCodec[A]): Assertion = roundtrip(c, a) def roundtrip[A](codec: RlpCodec[A], value: A): Assertion = { val encoded = codec.encode(value) encoded.isSuccessful shouldBe true val Attempt.Successful(DecodeResult(decoded, remainder)) = codec.decode(encoded.require) remainder shouldBe BitVector.empty decoded shouldBe value } def roundtripAll[A](codec: RlpCodec[A], as: collection.Iterable[A]): Unit = as foreach { a => roundtrip(codec, a) } def encodeError[A](codec: RlpCodec[A], a: A, err: Err): Assertion = { val encoded = codec.encode(a) encoded shouldBe Attempt.Failure(err) } def shouldDecodeFullyTo[A](codec: RlpCodec[A], buf: BitVector, expected: A): Assertion = { val Attempt.Successful(DecodeResult(actual, rest)) = codec decode buf rest shouldBe BitVector.empty actual shouldBe expected } }
Example 59
Source File: RlpEncoded.scala From iotchain with MIT License | 5 votes |
package jbok.codec.rlp import scodec.bits.{BitVector, ByteVector} // normally we construct `RlpEncoded` via rlp encoding // to avoid dumb problems final class RlpEncoded private (val bits: BitVector) extends AnyVal { def bytes: ByteVector = bits.bytes def byteArray: Array[Byte] = bits.toByteArray def decoded[A](implicit codec: RlpCodec[A]): Either[Throwable, A] = codec.decode(bits).toEither match { case Left(err) => Left(new Exception(err.messageWithContext)) case Right(result) => Right(result.value) } def isItem: Boolean = bits.bytes.headOption match { case Some(byte) => (0xff & byte) < RlpCodecHelper.listOffset case None => false } def isList: Boolean = !isItem def isEmptyItem: Boolean = this == RlpEncoded.emptyItem def isEmptyList: Boolean = this == RlpEncoded.emptyList override def toString: String = s"RlpEncoded(${bits.bytes})" } object RlpEncoded { def coerce(bits: BitVector): RlpEncoded = new RlpEncoded(bits) val emptyItem: RlpEncoded = RlpEncoded.coerce(BitVector(RlpCodecHelper.itemOffset.toByte)) val emptyList: RlpEncoded = RlpEncoded.coerce(BitVector(RlpCodecHelper.listOffset.toByte)) }
Example 60
Source File: implicits.scala From iotchain with MIT License | 5 votes |
package jbok.codec.json import io.circe._ import io.circe.generic.extras._ import jbok.codec.rlp.RlpEncoded import scodec.bits.ByteVector import shapeless._ import spire.math.SafeLong import scala.concurrent.duration.{Duration, FiniteDuration} import scala.util.Try @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf")) trait implicits { implicit val jsonConfig: Configuration = Configuration.default implicit val bytesJsonEncoder: Encoder[ByteVector] = Encoder.encodeString.contramap[ByteVector](_.toHex) implicit val bytesJsonDecoder: Decoder[ByteVector] = Decoder.decodeString.emap[ByteVector](ByteVector.fromHexDescriptive(_)) implicit val rlpJsonEncoder: Encoder[RlpEncoded] = bytesJsonEncoder.contramap(_.bytes) implicit val rlpJsonDecoder: Decoder[RlpEncoded] = bytesJsonDecoder.map(bytes => RlpEncoded.coerce(bytes.bits)) implicit val finiteDurationJsonEncoder: Encoder[FiniteDuration] = Encoder.encodeString.contramap[FiniteDuration](d => s"${d.length} ${d.unit.toString.toLowerCase}") implicit val finiteDurationJsonDecoder: Decoder[FiniteDuration] = Decoder.decodeString.emapTry[FiniteDuration](s => Try(Duration.apply(s).asInstanceOf[FiniteDuration])) implicit val bigIntJsonEncoder: Encoder[BigInt] = Encoder.encodeString.contramap[BigInt](_.toString(10)) implicit val bigIntJsonDecoder: Decoder[BigInt] = Decoder.decodeString.emapTry[BigInt](s => Try(BigInt(s))) implicit val safeLongJsonEncoder: Encoder[SafeLong] = Encoder.encodeString.contramap[SafeLong](_.toString) implicit val safeLongJsonDecoder: Decoder[SafeLong] = Decoder.decodeString.emapTry[SafeLong]( s => if (s.startsWith("0x")) Try(SafeLong(BigInt(s.drop(2), 16))) else Try(SafeLong(BigInt(s))) ) // key codecs implicit val bigIntKeyEncoder: KeyEncoder[BigInt] = KeyEncoder.encodeKeyString.contramap[BigInt](_.toString(10)) implicit val bigIntKeyDecoder: KeyDecoder[BigInt] = KeyDecoder.decodeKeyString.map[BigInt](BigInt.apply) implicit val safeLongKeyEncoder: KeyEncoder[SafeLong] = KeyEncoder.encodeKeyString.contramap[SafeLong](_.toString) implicit val safeLongKeyDecoder: KeyDecoder[SafeLong] = KeyDecoder.decodeKeyString.map[SafeLong](s => SafeLong(BigInt(s))) // codec for value classes implicit def decoderJsonValueClass[T <: AnyVal, V]( implicit g: Lazy[Generic.Aux[T, V :: HNil]], d: Decoder[V] ): Decoder[T] = Decoder.instance { cursor ⇒ d(cursor).map { value ⇒ g.value.from(value :: HNil) } } implicit def encoderJsonValueClass[T <: AnyVal, V]( implicit g: Lazy[Generic.Aux[T, V :: HNil]], e: Encoder[V] ): Encoder[T] = Encoder.instance { value ⇒ e(g.value.to(value).head) } } object implicits extends implicits
Example 61
Source File: Contract.scala From iotchain with MIT License | 5 votes |
package jbok.sdk import fastparse.Parsed import io.circe.generic.extras._ import jbok.evm.solidity.SolidityParser import jbok.evm.solidity.ABIDescription import jbok.evm.solidity.ABIDescription.ContractDescription import scodec.bits.ByteVector import _root_.io.circe.syntax._ import jbok.codec.json.implicits._ import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel} import scala.scalajs.js.JSConverters._ import scala.scalajs.js.UndefOr @JSExportTopLevel("Contracts") @JSExportAll @ConfiguredJsonCodec final case class Contracts(contractDescriptions: List[ContractDescription]) { private lazy val contracts = contractDescriptions.map(cd => cd.name -> cd).toMap private def methods(name: String): Option[Map[String, ABIDescription.FunctionDescription]] = contracts.get(name).map(_.methods.map(method => method.name -> method).toMap) def encode(contractName: String, method: String, param: String): UndefOr[String] = (for { function <- methods(contractName).flatMap(_.get(method)) returns = function.encode(param) match { case Right(value) => value.toHex case Left(e) => e.toString } } yield returns).orUndefined def decode(contractName: String, method: String, param: String): UndefOr[String] = (for { function <- methods(contractName).flatMap(_.get(method)) result <- ByteVector.fromHex(param) returns = function.decode(result) match { case Right(value) => value.noSpaces case Left(e) => e.toString } } yield returns).orUndefined } @ConfiguredJsonCodec final case class ParsedResult(contracts: Option[Contracts], error: String) @JSExportTopLevel("ContractParser") @JSExportAll object ContractParser { def parse(code: String): String = { val result = SolidityParser.parseSource(code) if (result.isSuccess) { ParsedResult(Some(Contracts(result.get.value.ABI)), "").asJson.noSpaces } else { ParsedResult(None, result.asInstanceOf[Parsed.Failure].trace().longAggregateMsg).asJson.noSpaces } } }
Example 62
Source File: ByteUtils.scala From iotchain with MIT License | 5 votes |
package jbok.common import java.nio.{ByteBuffer, ByteOrder} import scodec.bits.ByteVector object ByteUtils { def or(arrays: ByteVector*): ByteVector = { require(arrays.map(_.length).distinct.length <= 1, "All the arrays should have the same length") require(arrays.nonEmpty, "There should be one or more arrays") val zeroes = ByteVector.fill(arrays.headOption.map(_.length).getOrElse(0))(0.toByte) arrays.foldLeft[ByteVector](zeroes) { case (acc, cur) => acc or cur } } def and(arrays: ByteVector*): ByteVector = { require(arrays.map(_.length).distinct.length <= 1, "All the arrays should have the same length") require(arrays.nonEmpty, "There should be one or more arrays") val ones = ByteVector.fill(arrays.headOption.map(_.length).getOrElse(0))(0xFF.toByte) arrays.foldLeft[ByteVector](ones) { case (acc, cur) => acc and cur } } def bytesToInts(bytes: Array[Byte]): Array[Int] = bytes.grouped(4).map(getIntFromWord).toArray def intsToBytes(input: Array[Int]): Array[Byte] = input.flatMap { i => Array( (i & 0xFF).toByte, ((i >> 8) & 0xFF).toByte, ((i >> 16) & 0xFF).toByte, ((i >> 24) & 0xFF).toByte ) } def getIntFromWord(arr: Array[Byte]): Int = ByteBuffer.wrap(arr, 0, 4).order(ByteOrder.LITTLE_ENDIAN).getInt }
Example 63
package jbok.common import jbok.common.math.N import org.scalacheck.Arbitrary._ import org.scalacheck.Gen import org.scalacheck.Gen.Choose import scodec.bits.ByteVector import spire.laws.{gen => SpireGen} import spire.math.{Natural, SafeLong} object gen { def int(min: Int = Int.MinValue, max: Int = Int.MaxValue): Gen[Int] = Gen.choose(min, max) val hexChar: Gen[Char] = Gen.oneOf("0123456789abcdef") def hex(min: Int, max: Int): Gen[String] = for { size <- Gen.chooseNum(min, max) chars <- Gen.listOfN(size, hexChar) } yield chars.mkString val natural: Gen[Natural] = SpireGen.natural val safeLong: Gen[SafeLong] = SpireGen.safeLong val N: Gen[N] = safeLong.map(_.abs) val bigInt: Gen[BigInt] = arbitrary[BigInt].map(_.abs) val byteArray: Gen[Array[Byte]] = Gen.listOf(arbitrary[Byte]).map(_.toArray) val byteVector: Gen[ByteVector] = byteArray.map(ByteVector.apply) def boundedByteArray(l: Int, u: Int): Gen[Array[Byte]] = Gen.choose(l, u).flatMap(size => sizedByteArray(size)) def boundedByteVector(l: Int, u: Int): Gen[ByteVector] = Gen.choose(l, u).flatMap(size => sizedByteVector(size)) def sizedByteArray(size: Int): Gen[Array[Byte]] = Gen.listOfN(size, arbitrary[Byte]).map(_.toArray) def sizedByteVector(size: Int): Gen[ByteVector] = Gen.listOfN(size, arbitrary[Byte]).map(ByteVector.apply) def posNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = Gen.posNum[T] def boundedList[T](minSize: Int, maxSize: Int, gen: Gen[T]): Gen[List[T]] = Gen.choose(minSize, maxSize).flatMap(size => Gen.listOfN(size, gen)) }
Example 64
Source File: testkit.scala From iotchain with MIT License | 5 votes |
package jbok.persistent import cats.effect.{IO, Resource} import jbok.codec.HexPrefix import jbok.common.{gen, FileUtil} import jbok.persistent.rocksdb.RocksKVStore import org.scalacheck.{Arbitrary, Gen} import scodec.bits.ByteVector import jbok.codec.rlp.implicits._ import jbok.persistent.mpt.MptNode import jbok.persistent.mpt.MptNode._ import cats.implicits._ object testkit { implicit def arbColumnFamily: Arbitrary[ColumnFamily] = Arbitrary { Gen.alphaNumStr.map(ColumnFamily.apply) } def testRocksKVStore(cfs: List[ColumnFamily] = List(ColumnFamily.default)): Resource[IO, KVStore[IO]] = FileUtil[IO].temporaryDir().flatMap { dir => RocksKVStore.resource[IO](dir.path, cfs) } val testMemoryKVStore: Resource[IO, KVStore[IO]] = Resource.liftF(MemoryKVStore[IO]) def testRocksStageStore(cfs: List[ColumnFamily] = List(ColumnFamily.default)): Resource[IO, StageKVStore[IO, ByteVector, ByteVector]] = testRocksKVStore(cfs).map(inner => StageKVStore(SingleColumnKVStore[IO, ByteVector, ByteVector](ColumnFamily.default, inner))) val testMemoryStageStore: Resource[IO, StageKVStore[IO, ByteVector, ByteVector]] = testMemoryKVStore.map(inner => StageKVStore(SingleColumnKVStore[IO, ByteVector, ByteVector](ColumnFamily.default, inner))) implicit lazy val arbLeafNode: Arbitrary[LeafNode] = Arbitrary { for { key <- gen.boundedByteVector(0, 1024) value <- gen.boundedByteVector(0, 1024) } yield LeafNode(HexPrefix.encodedToNibbles(key.encoded), value.encoded) } implicit lazy val arbBranchNode: Arbitrary[BranchNode] = Arbitrary { for { children <- Gen .listOfN(16, Gen.oneOf(gen.sizedByteVector(32).map(_.asLeft), arbMptNode.arbitrary.map(_.asRight))) .map(childrenList => childrenList.map(child => Some(child))) value <- gen.byteVector } yield BranchNode(children, Some(value.encoded)) } implicit lazy val arbExtensionNode: Arbitrary[ExtensionNode] = Arbitrary { for { key <- gen.boundedByteVector(0, 1024) value <- gen.boundedByteVector(0, 1024) } yield ExtensionNode(HexPrefix.encodedToNibbles(key.encoded), Left(value)) } implicit lazy val arbMptNode: Arbitrary[MptNode] = Arbitrary { Gen.oneOf[MptNode](arbLeafNode.arbitrary, arbExtensionNode.arbitrary, arbBranchNode.arbitrary) } }
Example 65
Source File: KVStoreSpec.scala From iotchain with MIT License | 5 votes |
package jbok.persistent import cats.effect.{IO, Resource} import cats.implicits._ import jbok.common.CommonSpec import jbok.persistent.testkit._ import scodec.bits.ByteVector class KVStoreSpec extends CommonSpec { val default = ColumnFamily.default val cfa = ColumnFamily("a") val cfb = ColumnFamily("b") val cfs = List(default, cfa, cfb) def test(name: String, resource: Resource[IO, KVStore[IO]]): Unit = s"KVStore ${name}" should { "respect column family" in withResource(resource) { store => val key = "key".getBytes val a = "a".getBytes val b = "b".getBytes for { _ <- store.put(cfa, key, a) _ <- store.put(cfb, key, b) value <- store.get(default, key) _ = value shouldBe None size <- store.size(default) _ = size shouldBe 0 value <- store.get(cfa, key) _ = value.get shouldEqual a size <- store.size(cfa) _ = size shouldBe 1 value <- store.get(cfb, key) _ = value.get shouldEqual b size <- store.size(cfb) _ = size shouldBe 1 } yield () } "write batch" in { val cf = default forAll { m: Map[ByteVector, ByteVector] => val p = resource.use { store => val kvs = m.toList.map { case (k, v) => k.toArray -> v.toArray } for { _ <- store.writeBatch(cf, kvs, Nil) res <- store.toList(cf) _ = res.map { case (k, v) => ByteVector(k) -> ByteVector(v) }.toMap shouldBe m res <- store.size(cf) _ = res shouldBe kvs.size } yield () } p.unsafeRunSync() } } "toList" in { forAll { (m1: Map[ByteVector, ByteVector], m2: Map[ByteVector, ByteVector]) => val kvs1 = m1.toList.map { case (k, v) => k.toArray -> v.toArray } val kvs2 = m2.toList.map { case (k, v) => k.toArray -> v.toArray } val p = resource.use { store => for { _ <- kvs1.traverse(t => store.put(cfa, t._1, t._2)) _ <- kvs2.traverse(t => store.put(cfb, t._1, t._2)) res <- store.toList(cfa) _ = res.map { case (k, v) => ByteVector(k) -> ByteVector(v) }.toMap shouldBe m1 res <- store.toList(cfb) _ = res.map { case (k, v) => ByteVector(k) -> ByteVector(v) }.toMap shouldBe m2 } yield () } p.unsafeRunSync() } } } test("rocksdb", testRocksKVStore(cfs)) test("memory", testMemoryKVStore) }
Example 66
Source File: StageKVStoreSpec.scala From iotchain with MIT License | 5 votes |
package jbok.persistent import cats.effect.{IO, Resource} import jbok.common.CommonSpec import scodec.bits.ByteVector import jbok.persistent.testkit._ class StageKVStoreSpec extends CommonSpec { def test(name: String, resource: Resource[IO, StageKVStore[IO, ByteVector, ByteVector]]): Unit = s"StageKVStore $name" should { val key = ByteVector("key".getBytes) val value = ByteVector("value".getBytes) "not write inserts until commit" in withResource(resource) { stage => val updated = stage .put(key, value) for { res <- updated.mustGet(key) _ = res shouldBe value res <- updated.inner.get(key) _ = res shouldBe None committed <- updated.commit res <- committed.inner.get(key) _ = res shouldBe Some(value) res <- stage.mustGet(key) _ = res shouldBe value } yield () } } test("rocksdb", testRocksStageStore()) test("memory", testMemoryStageStore) }
Example 67
Source File: ProgramSpec.scala From iotchain with MIT License | 5 votes |
package jbok.evm import jbok.common.{gen, CommonSpec} import org.scalacheck.Arbitrary import scodec.bits.ByteVector class ProgramSpec extends CommonSpec { val CodeSize: Int = Byte.MaxValue val PositionsSize = 10 val nonPushOp: Byte = JUMP.code val invalidOpCode: Byte = 0xef.toByte implicit val arbPositionSet: Arbitrary[Set[Int]] = Arbitrary(gen.boundedList(0, PositionsSize, gen.int(0, CodeSize)).map(_.toSet)) "program" should { "detect all jump destinations if there are no push op" in { forAll { jumpDestLocations: Set[Int] => val code = ByteVector((0 to CodeSize).map { i => if (jumpDestLocations.contains(i)) JUMPDEST.code else nonPushOp }.toArray) val program = Program(code) program.validJumpDestinations shouldBe jumpDestLocations } } "detect all jump destinations if there are push op" in { forAll { (jumpDestLocations: Set[Int], pushOpLocations: Set[Int]) => val code = ByteVector((0 to CodeSize).map { i => if (jumpDestLocations.contains(i)) JUMPDEST.code else if (pushOpLocations.contains(i)) PUSH1.code else nonPushOp }.toArray) val program = Program(code) //Removing the PUSH1 that would be used as a parameter of another PUSH1 // Example: In "PUSH1 PUSH1 JUMPDEST", the JUMPDEST is a valid jump destination val pushOpLocationsNotParameters = (pushOpLocations diff jumpDestLocations).toList.sorted .foldLeft(List.empty[Int]) { case (recPushOpLocations, i) => if (recPushOpLocations.lastOption.contains(i - 1)) recPushOpLocations else recPushOpLocations :+ i } val jumpDestLocationsWithoutPushBefore = jumpDestLocations .filterNot(i => pushOpLocationsNotParameters.contains(i - 1)) .filter(i => 0 <= i && i <= CodeSize) program.validJumpDestinations shouldBe jumpDestLocationsWithoutPushBefore } } "detect all jump destinations if there are invalid ops" in { forAll { (jumpDestLocations: Set[Int], invalidOpLocations: Set[Int]) => val code = ByteVector((0 to CodeSize).map { i => if (jumpDestLocations.contains(i)) JUMPDEST.code else if (invalidOpLocations.contains(i)) invalidOpCode else nonPushOp }.toArray) val program = Program(code) program.validJumpDestinations shouldBe jumpDestLocations } } "detect all instructions as jump destinations if they are" in { val code = ByteVector((0 to CodeSize).map(_ => JUMPDEST.code).toArray) val program = Program(code) program.validJumpDestinations shouldBe (0 to CodeSize).toSet } } }
Example 68
Source File: Assembly.scala From iotchain with MIT License | 5 votes |
package jbok.evm import jbok.common.math.N import jbok.evm.Assembly._ import scodec.bits.ByteVector object Assembly { sealed trait ByteCode { def bytes: ByteVector } implicit class OpCodeAsByteCode(val op: OpCode) extends ByteCode { def bytes: ByteVector = ByteVector(op.code) } implicit class IntAsByteCode(val i: Int) extends ByteCode { def bytes: ByteVector = ByteVector(i.toByte) } implicit class ByteAsByteCode(val byte: Byte) extends ByteCode { def bytes: ByteVector = ByteVector(byte) } implicit class ByteVectorAsByteCode(val bytes: ByteVector) extends ByteCode } final case class Assembly(byteCode: ByteCode*) { val code: ByteVector = byteCode.foldLeft(ByteVector.empty)(_.bytes ++ _.bytes) val program: Program = Program(code) def linearConstGas(config: EvmConfig): N = byteCode.foldLeft(N(0)) { case (g, b: OpCodeAsByteCode) => g + b.op.constGasFn(config.feeSchedule) case (g, _) => g } }
Example 69
Source File: CallOpcodesSpecByzantium.scala From iotchain with MIT License | 5 votes |
package jbok.evm import cats.effect.IO import jbok.core.CoreSpec import jbok.core.ledger.History import jbok.core.models.{Account, Address, UInt256} import jbok.persistent.MemoryKVStore import scodec.bits.ByteVector class CallOpcodesSpecByzantium extends CoreSpec { val evmConfig = EvmConfig.ByzantiumConfigBuilder(None) val store = MemoryKVStore[IO].unsafeRunSync() val history = History(store, chainId) val startState = history.getWorldState(noEmptyAccounts = true).unsafeRunSync() val fxt = new CallOpFixture(evmConfig, startState) "STATICCALL" should { "call a program that executes a SELFDESTRUCT" should { val context = fxt.context.copy(world = fxt.worldWithSelfDestructProgram) val call = fxt.CallResult(op = STATICCALL, context) "return 0" in { call.stateOut.stack.pop._1 shouldBe UInt256.zero } } "call a precompiled contract" should { val contractAddress = Address(1) // ECDSA recovery val invalidSignature = ByteVector(Array.fill(128)(0.toByte)) val world = fxt.worldWithoutExtAccount.putAccount(contractAddress, Account(balance = 1)) val context = fxt.context.copy(world = world) val call = fxt.CallResult( op = STATICCALL, context = context, to = contractAddress, inputData = invalidSignature, inOffset = 0, inSize = 128, outOffset = 0, outSize = 128 ) "compute a correct result" in { // For invalid signature the return data should be empty, so the memory should not be modified. // This is more interesting than checking valid signatures which are tested elsewhere val (result, _) = call.stateOut.memory.load(call.outOffset, call.outSize) val expected = invalidSignature result shouldBe expected } "return 1" in { call.stateOut.stack.pop._1 shouldBe UInt256.one } "update precompiled contract's balance" in { call.extBalance shouldBe 1 } } "call a program that executes a REVERT" should { val context = fxt.context.copy(world = fxt.worldWithRevertProgram) val call = fxt.CallResult(op = STATICCALL, context) "return 0" in { call.stateOut.stack.pop._1 shouldBe UInt256.zero } "consume correct gas" in { call.stateOut.gasUsed shouldBe 709 } } } }
Example 70
Source File: HistorySpec.scala From iotchain with MIT License | 5 votes |
package jbok.core.ledger import cats.effect.IO import cats.implicits._ import jbok.core.ledger.TypedBlock.MinedBlock import jbok.core.models._ import jbok.core.{CoreSpec, StatefulGen} import scodec.bits.ByteVector import jbok.crypto._ class HistorySpec extends CoreSpec { "History" should { val objects = locator.unsafeRunSync() val history = objects.get[History[IO]] "load genesis config" in { val addresses = genesis.alloc.keysIterator.toList val accounts = addresses.flatMap(addr => history.getAccount(addr, 0).unsafeRunSync()) accounts.length shouldBe addresses.length } // storage and codes "put and get code" in { forAll { code: ByteVector => history.putCode(code).unsafeRunSync() history.getCode(code.kec256).unsafeRunSync().getOrElse(ByteVector.empty) shouldBe code } } // mapping "put block header should update number hash mapping" in { history.getHashByBlockNumber(0).unsafeRunSync() shouldBe history.genesisHeader.unsafeRunSync().hash.some } "put block body should update tx location mapping" in { val txs = random(StatefulGen.transactions(1, 1, history)) val block = random(StatefulGen.block(None, txs.some)) history.putBlockBody(block.header.hash, block.body).unsafeRunSync() val location = history.getTransactionLocation(txs.head.hash).unsafeRunSync() location shouldBe Some(TransactionLocation(block.header.hash, 0)) } "delBlock should delete all relevant parts" in check { objects => val history = objects.get[History[IO]] val mined = random[MinedBlock](StatefulGen.minedBlock()) for { _ <- history.putBlockAndReceipts(mined.block, mined.receipts) res <- history.getBlockHeaderByHash(mined.block.header.hash) _ = res shouldBe Some(mined.block.header) res <- history.getBlockBodyByHash(mined.block.header.hash) _ = res shouldBe Some(mined.block.body) res <- history.getBlockByHash(mined.block.header.hash) _ = res shouldBe Some(mined.block) res <- history.getReceiptsByHash(mined.block.header.hash) _ = res shouldBe Some(mined.receipts) res <- history.getBestBlockNumber _ = res shouldBe mined.block.header.number res <- history.getTotalDifficultyByHash(mined.block.header.hash) _ = res shouldBe Some(mined.block.header.difficulty) res <- history.getHashByBlockNumber(mined.block.header.number) _ = res shouldBe Some(mined.block.header.hash) // del _ <- history.delBlock(mined.block.header.hash) res <- history.getBlockHeaderByHash(mined.block.header.hash) _ = res shouldBe None res <- history.getBlockBodyByHash(mined.block.header.hash) _ = res shouldBe None res <- history.getBlockByHash(mined.block.header.hash) _ = res shouldBe None res <- history.getReceiptsByHash(mined.block.header.hash) _ = res shouldBe None res <- history.getTotalDifficultyByHash(mined.block.header.hash) _ = res shouldBe None res <- history.getHashByBlockNumber(mined.block.header.number) _ = res shouldBe None } yield () } } }
Example 71
Source File: ExecEnv.scala From iotchain with MIT License | 5 votes |
package jbok.evm import jbok.core.models._ import scodec.bits.ByteVector final case class ExecEnv( ownerAddr: Address, callerAddr: Address, originAddr: Address, gasPrice: UInt256, inputData: ByteVector, value: UInt256, program: Program, blockHeader: BlockHeader, callDepth: Int, noSelfCall: Boolean = false )
Example 72
Source File: ProgramResult.scala From iotchain with MIT License | 5 votes |
package jbok.evm import jbok.common.math.N import jbok.core.models.{Address, TxLogEntry} import scodec.bits.ByteVector final case class ProgramResult[F[_]]( returnData: ByteVector, gasRemaining: N, world: WorldState[F], addressesToDelete: Set[Address], logs: List[TxLogEntry], internalTxs: List[InternalTransaction], gasRefund: N, error: Option[ProgramError], isRevert: Boolean = false, contractAddress: Option[Address] = None, )
Example 73
Source File: Program.scala From iotchain with MIT License | 5 votes |
package jbok.evm import scodec.bits.ByteVector import scala.annotation.tailrec @tailrec private def validJumpDestinationsAfterPosition(pos: Int, accum: Set[Int] = Set.empty): Set[Int] = if (pos < 0 || pos >= length) accum else { val byte = code(pos) val opCode = frontierConfig.byteToOpCode.get(byte) // we only need to check PushOp and JUMPDEST, they are both present in Frontier opCode match { case Some(pushOp: PushOp) => validJumpDestinationsAfterPosition(pos + pushOp.i + 2, accum) case Some(JUMPDEST) => validJumpDestinationsAfterPosition(pos + 1, accum + pos) case _ => validJumpDestinationsAfterPosition(pos + 1, accum) } } }
Example 74
Source File: ProgramContext.scala From iotchain with MIT License | 5 votes |
package jbok.evm import cats.effect.Sync import jbok.common.math.N import jbok.core.models.{Address, BlockHeader, SignedTransaction, UInt256} import scodec.bits.ByteVector object ProgramContext { def apply[F[_]: Sync]( stx: SignedTransaction, senderAddress: Address, recipientAddress: Address, program: Program, blockHeader: BlockHeader, world: WorldState[F], config: EvmConfig ): ProgramContext[F] = { // YP eq (91) val inputData = if (stx.isContractInit) ByteVector.empty else stx.payload val env = ExecEnv( recipientAddress, senderAddress, senderAddress, UInt256(stx.gasPrice), inputData, UInt256(stx.value), program, blockHeader, callDepth = 0 ) val gasLimit = stx.gasLimit - config.calcTransactionIntrinsicGas(stx.payload, stx.isContractInit) ProgramContext[F](env, recipientAddress, gasLimit, world, config) } } final case class ProgramContext[F[_]: Sync]( env: ExecEnv, receivingAddr: Address, startGas: N, world: WorldState[F], config: EvmConfig, initialAddressesToDelete: Set[Address] = Set.empty, readOnly: Boolean = false )
Example 75
Source File: BloomFilter.scala From iotchain with MIT License | 5 votes |
package jbok.core.ledger import jbok.core.models.TxLogEntry import jbok.common.ByteUtils import scodec.bits.ByteVector import jbok.crypto._ object BloomFilter { val BloomFilterByteSize: Int = 256 val BloomFilterBitSize: Int = BloomFilterByteSize * 8 val EmptyBloomFilter: ByteVector = ByteVector(Array.fill(BloomFilterByteSize)(0.toByte)) private val IntIndexesToAccess: Set[Int] = Set(0, 2, 4) def containsAnyOf(bloomFilterBytes: ByteVector, toCheck: List[ByteVector]): Boolean = toCheck.exists { bytes => val bloomFilterForBytes = bloomFilter(bytes) val andResult = ByteUtils.and(bloomFilterForBytes, bloomFilterBytes) andResult == bloomFilterForBytes } def create(logs: Seq[TxLogEntry]): ByteVector = { val bloomFilters = logs.map(createBloomFilterForLogEntry) if (bloomFilters.isEmpty) EmptyBloomFilter else ByteUtils.or(bloomFilters: _*) } // Bloom filter function that reduces a log to a single 256-byte hash based on equation 24 from the YP private def createBloomFilterForLogEntry(logEntry: TxLogEntry): ByteVector = { val dataForBloomFilter = logEntry.loggerAddress.bytes +: logEntry.logTopics val bloomFilters = dataForBloomFilter.map(bytes => bloomFilter(bytes)) ByteUtils.or(bloomFilters: _*) } // Bloom filter that sets 3 bits out of 2048 based on equations 25-28 from the YP private def bloomFilter(bytes: ByteVector): ByteVector = { val hashedBytes = bytes.kec256 val bitsToSet = IntIndexesToAccess.map { i => val index16bit = (hashedBytes(i + 1) & 0xFF) + ((hashedBytes(i) & 0xFF) << 8) index16bit % BloomFilterBitSize //Obtain only 11 bits from the index } bitsToSet.foldLeft(EmptyBloomFilter) { case (prevBloom, index) => setBit(prevBloom, index) }.reverse } private def setBit(bytes: ByteVector, bitIndex: Int): ByteVector = { require(bitIndex / 8 < bytes.length, "Only bits between the bytes array should be set") val byteIndex = bitIndex / 8 val newByte: Byte = (bytes(byteIndex) | 1 << (bitIndex % 8).toByte).toByte bytes.update(byteIndex, newByte) } }
Example 76
Source File: AccountAPI.scala From iotchain with MIT License | 5 votes |
package jbok.core.api import io.circe.generic.extras.ConfiguredJsonCodec import jbok.core.models.{Account, Address, SignedTransaction} import scodec.bits.ByteVector import jbok.codec.json.implicits._ import jbok.common.math.N import jbok.network.rpc.PathName @ConfiguredJsonCodec final case class HistoryTransaction( txHash: ByteVector, nonce: N, fromAddress: Address, toAddress: Address, value: N, payload: String, v: N, r: N, s: N, gasUsed: N, gasPrice: N, blockNumber: N, blockHash: ByteVector, location: Int ) @PathName("account") trait AccountAPI[F[_]] { def getAccount(address: Address, tag: BlockTag = BlockTag.latest): F[Account] def getCode(address: Address, tag: BlockTag = BlockTag.latest): F[ByteVector] def getBalance(address: Address, tag: BlockTag = BlockTag.latest): F[N] def getStorageAt(address: Address, position: N, tag: BlockTag = BlockTag.latest): F[ByteVector] def getTransactions(address: Address, page: Int, size: Int): F[List[HistoryTransaction]] def getTransactionsByNumber(number: Int): F[List[HistoryTransaction]] // def getTokenTransactions(address: Address, contract: Option[Address]): F[List[SignedTransaction]] def getPendingTxs(address: Address): F[List[SignedTransaction]] def getEstimatedNonce(address: Address): F[N] }
Example 77
Source File: PersonalAPI.scala From iotchain with MIT License | 5 votes |
package jbok.core.api import jbok.common.math.N import jbok.core.models.Address import jbok.network.rpc.PathName import scodec.bits.ByteVector @PathName("personal") trait PersonalAPI[F[_]] { def importRawKey(privateKey: ByteVector, passphrase: String): F[Address] def newAccount(passphrase: String): F[Address] def delAccount(address: Address): F[Boolean] def listAccounts: F[List[Address]] def changePassphrase(address: Address, oldPassphrase: String, newPassphrase: String): F[Boolean] def sendTransaction( from: Address, passphrase: String, to: Option[Address] = None, value: Option[N] = None, gasLimit: Option[N] = None, gasPrice: Option[N] = None, nonce: Option[N] = None, data: Option[ByteVector] = None, ): F[ByteVector] }
Example 78
Source File: ContractAPI.scala From iotchain with MIT License | 5 votes |
package jbok.core.api import io.circe.generic.extras.ConfiguredJsonCodec import jbok.core.models.Address import scodec.bits.ByteVector import jbok.codec.json.implicits._ import jbok.common.math.N import jbok.network.rpc.PathName import scala.scalajs.js.annotation.JSExportAll @JSExportAll @ConfiguredJsonCodec final case class CallTx( from: Option[Address], to: Option[Address], gas: Option[N], gasPrice: N, value: N, data: ByteVector ) @PathName("contract") trait ContractAPI[F[_]] { // def getABI(address: Address): F[Option[ContractDef]] // // def getSourceCode(address: Address): F[Option[String]] def call(callTx: CallTx, tag: BlockTag = BlockTag.latest): F[ByteVector] def getEstimatedGas(callTx: CallTx, tag: BlockTag = BlockTag.latest): F[N] def getGasPrice: F[N] }
Example 79
Source File: NewBlock.scala From iotchain with MIT License | 5 votes |
package jbok.core.messages import io.circe.generic.extras.ConfiguredJsonCodec import jbok.codec.json.implicits._ import jbok.codec.rlp.RlpCodec import jbok.common.math.N import jbok.core.models.Block import scodec.bits.ByteVector @ConfiguredJsonCodec final case class BlockHash(hash: ByteVector, number: N) object BlockHash { val name = "BlockHash" implicit val rlpCodec: RlpCodec[BlockHash] = RlpCodec.gen[BlockHash] } @ConfiguredJsonCodec final case class NewBlockHashes(hashes: List[BlockHash]) object NewBlockHashes { val name = "NewBlockHashes" implicit val rlpCodec: RlpCodec[NewBlockHashes] = RlpCodec.gen[NewBlockHashes] } @ConfiguredJsonCodec final case class NewBlock(block: Block) object NewBlock { val name = "NewBlock" implicit val rlpCodec: RlpCodec[NewBlock] = RlpCodec.gen[NewBlock] }
Example 80
Source File: Account.scala From iotchain with MIT License | 5 votes |
package jbok.core.models import io.circe.generic.extras.ConfiguredJsonCodec import jbok.codec.json.implicits._ import jbok.crypto._ import jbok.persistent.mpt.MerklePatriciaTrie import scodec.bits.ByteVector import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel} @JSExportTopLevel("Account") @JSExportAll @ConfiguredJsonCodec final case class Account( nonce: UInt256 = 0, balance: UInt256 = 0, storageRoot: ByteVector = Account.EmptyStorageRootHash, codeHash: ByteVector = Account.EmptyCodeHash ) { def increaseBalance(value: UInt256): Account = copy(balance = balance + value) def increaseNonce(value: UInt256 = 1): Account = copy(nonce = nonce + value) def withCode(codeHash: ByteVector): Account = copy(codeHash = codeHash) def withStorage(storageRoot: ByteVector): Account = copy(storageRoot = storageRoot) def nonEmptyCodeOrNonce(startNonce: UInt256 = UInt256.zero): Boolean = nonce != startNonce || codeHash != Account.EmptyCodeHash } object Account { val EmptyStorageRootHash: ByteVector = MerklePatriciaTrie.emptyRootHash val EmptyCodeHash: ByteVector = ByteVector.empty.kec256 def empty(startNonce: UInt256 = UInt256.zero): Account = Account(nonce = startNonce, storageRoot = EmptyStorageRootHash, codeHash = EmptyCodeHash) }
Example 81
Source File: Transaction.scala From iotchain with MIT License | 5 votes |
package jbok.core.models import io.circe.generic.extras.ConfiguredJsonCodec import scodec.bits.ByteVector import jbok.codec.json.implicits._ import jbok.common.math.N import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel} @JSExportTopLevel("Transaction") @JSExportAll @ConfiguredJsonCodec final case class Transaction( nonce: N, gasPrice: N, gasLimit: N, receivingAddress: Option[Address], value: N, payload: ByteVector )
Example 82
Source File: Peer.scala From iotchain with MIT License | 5 votes |
package jbok.core.peer import cats.effect.concurrent.Ref import cats.effect.{Concurrent, Sync} import cats.implicits._ import fs2.concurrent.Queue import jbok.core.messages.{SignedTransactions, Status} import jbok.network.Message import scodec.bits.ByteVector import jbok.codec.rlp.implicits._ import jbok.common.log.Logger import jbok.common.math.N import jbok.crypto._ final case class Peer[F[_]]( uri: PeerUri, queue: Queue[F, Message[F]], status: Ref[F, Status], knownBlocks: Ref[F, Set[ByteVector]], knownTxs: Ref[F, Set[ByteVector]] )(implicit F: Sync[F]) { import Peer._ private[this] val log = Logger[F] def hasBlock(blockHash: ByteVector): F[Boolean] = knownBlocks.get.map(_.contains(blockHash)) def hasTxs(stxs: SignedTransactions): F[Boolean] = knownTxs.get.map(_.contains(stxs.encoded.bytes.kec256)) def markBlock(blockHash: ByteVector, number: N): F[Unit] = knownBlocks.update(s => s.take(MaxKnownBlocks - 1) + blockHash) >> status.update(s => s.copy(bestNumber = s.bestNumber.max(number))) def markTxs(stxs: SignedTransactions): F[Unit] = knownTxs.update(known => known.take(MaxKnownTxs - 1) + stxs.encoded.bytes.kec256) def markStatus(newStatus: Status): F[Unit] = status.update(s => if (newStatus.td > s.td) s.copy(bestNumber = newStatus.bestNumber, td = newStatus.td) else s) } object Peer { val MaxKnownTxs = 32768 val MaxKnownBlocks = 1024 def apply[F[_]: Concurrent](uri: PeerUri, status: Status): F[Peer[F]] = for { queue <- Queue.circularBuffer[F, Message[F]](100000) status <- Ref.of[F, Status](status) knownBlocks <- Ref.of[F, Set[ByteVector]](Set.empty) knownTxs <- Ref.of[F, Set[ByteVector]](Set.empty) } yield Peer[F](uri, queue, status, knownBlocks, knownTxs) }
Example 83
Source File: KeyStore.scala From iotchain with MIT License | 5 votes |
package jbok.core.keystore import jbok.core.models.Address import scodec.bits.ByteVector object KeyStoreError { final case object KeyNotFound extends Exception("KeyNotFound") final case object KeyAlreadyExist extends Exception("KeyAlreadyExist") final case object DecryptionFailed extends Exception("DecryptionFailed") final case object InvalidKeyFormat extends Exception("InvalidKeyFormat") final case class IOError(msg: String) extends Exception(s"IO error, ${msg}") } trait KeyStore[F[_]] { def newAccount(passphrase: String): F[Address] def readPassphrase(prompt: String): F[String] def importPrivateKey(key: ByteVector, passphrase: String): F[Address] def listAccounts: F[List[Address]] def unlockAccount(address: Address, passphrase: String): F[Wallet] def deleteAccount(address: Address): F[Boolean] def changePassphrase( address: Address, oldPassphrase: String, newPassphrase: String ): F[Boolean] }
Example 84
Source File: MockingKeyStore.scala From iotchain with MIT License | 5 votes |
package jbok.core.keystore import cats.effect.Sync import cats.implicits._ import cats.effect.concurrent.Ref import jbok.core.models.Address import jbok.crypto.signature.{ECDSA, KeyPair, Signature} import scodec.bits.ByteVector final class MockingKeyStore[F[_]](implicit F: Sync[F]) extends KeyStore[F] { private val m: Ref[F, Map[Address, KeyPair]] = Ref.unsafe(Map.empty) override def newAccount(passphrase: String): F[Address] = for { kp <- Signature[ECDSA].generateKeyPair[F]() _ <- m.update(_ + (Address(kp) -> kp)) } yield Address(kp) override def readPassphrase(prompt: String): F[String] = ??? override def importPrivateKey(key: ByteVector, passphrase: String): F[Address] = for { secret <- KeyPair.Secret(key).pure[F] public <- Signature[ECDSA].generatePublicKey[F](secret) kp = KeyPair(public, secret) address = Address(kp) _ <- m.update(_ + (address -> kp)) } yield address override def listAccounts: F[List[Address]] = m.get.map(_.keys.toList) override def unlockAccount(address: Address, passphrase: String): F[Wallet] = m.get.map(_(address)).map { kp => Wallet(Address(kp), kp) } override def deleteAccount(address: Address): F[Boolean] = m.update(_ - address).as(true) override def changePassphrase(address: Address, oldPassphrase: String, newPassphrase: String): F[Boolean] = F.pure(true) } object MockingKeyStore { def withInitKeys[F[_]: Sync](initKeys: List[KeyPair]): F[MockingKeyStore[F]] = { val keystore = new MockingKeyStore[F]() initKeys.traverse(kp => keystore.importPrivateKey(kp.secret.bytes, "")).as(keystore) } }
Example 85
Source File: byteVector.scala From refined with MIT License | 5 votes |
package eu.timepit.refined.scodec import eu.timepit.refined.api.Validate import eu.timepit.refined.collection.Size import eu.timepit.refined.internal.Resources import scodec.bits.ByteVector object byteVector extends ByteVectorValidate private[refined] trait ByteVectorValidate { implicit def byteVectorSizeValidate[P, RP]( implicit v: Validate.Aux[Long, P, RP] ): Validate.Aux[ByteVector, Size[P], Size[v.Res]] = new Validate[ByteVector, Size[P]] { override type R = Size[v.Res] override def validate(t: ByteVector): Res = { val r = v.validate(t.size) r.as(Size(r)) } override def showExpr(t: ByteVector): String = v.showExpr(t.size) override def showResult(t: ByteVector, r: Res): String = { val size = t.size val nested = v.showResult(size, r.detail.p) Resources.predicateTakingResultDetail(s"size($t) = $size", r, nested) } } }
Example 86
Source File: ByteVectorValidateSpec.scala From refined with MIT License | 5 votes |
package eu.timepit.refined.scodec import eu.timepit.refined.TestUtils._ import eu.timepit.refined.W import eu.timepit.refined.collection.Size import eu.timepit.refined.generic.Equal import eu.timepit.refined.numeric.Greater import eu.timepit.refined.scodec.byteVector._ import org.scalacheck.Prop._ import org.scalacheck.Properties import scodec.bits.ByteVector class ByteVectorValidateSpec extends Properties("ByteVectorValidate") { property("Size.isValid") = forAll { bytes: Array[Byte] => val bv = ByteVector(bytes) isValid[Size[Greater[W.`5L`.T]]](bv) ?= (bv.size > 5L) } property("Size.showExpr") = secure { showExpr[Size[Equal[W.`5L`.T]]](ByteVector.fromValidHex("0xdeadbeef")) ?= "(4 == 5)" } property("Size.showResult") = secure { showResult[Size[Equal[W.`5L`.T]]](ByteVector.fromValidHex("0xdeadbeef")) ?= "Predicate taking size(ByteVector(4 bytes, 0xdeadbeef)) = 4 failed: Predicate failed: (4 == 5)." } }
Example 87
Source File: Text.scala From benchmarks with Apache License 2.0 | 5 votes |
package com.rossabaker package benchmarks import org.openjdk.jmh.annotations._ @State(Scope.Thread) @Fork(2) @Measurement(iterations = 10) @Warmup(iterations = 10) @Threads(1) class Text extends BenchmarkUtils { val LoremIpsum: String = scala.io.Source.fromFile("testdata/lorem-ipsum.txt") .getLines .mkString("\n") val LoremIpsumBytes: Array[Byte] = LoremIpsum.getBytes(java.nio.charset.StandardCharsets.UTF_8) @Benchmark def fs2EncodeDecode(): String = { import _root_.fs2._, Stream._ emit(LoremIpsum) .covary[Task] .through(text.utf8Encode) .through(text.utf8Decode) .runFold("")(_ + _) .unsafeRun } @Benchmark def fs2Wc(): Int = { import _root_.fs2._, Stream._ emit(LoremIpsum) .covary[Task] .through(text.lines) .fold(0)((acc, _) => acc + 1) .runLast .unsafeRun .getOrElse(0) } @Benchmark def scalazStreamEncodeDecode(): String = { import _root_.scalaz.stream._, Process._ import scodec.bits.ByteVector import scalaz.std.string._ emit(LoremIpsum) .toSource .pipe(text.utf8Encode) .pipe(text.utf8Decode) .runFoldMap(identity) .unsafePerformSync } @Benchmark def scalazStreamWc(): Int = { import _root_.scalaz.stream._, Process._ import scodec.bits.ByteVector import scalaz.std.anyVal._ emit(LoremIpsum) .toSource .pipe(text.lines()) .fold(0)((acc, _) => acc + 1) .runLastOr(0) .unsafePerformSync } }
Example 88
Source File: UUIDUtils.scala From seals with Apache License 2.0 | 5 votes |
package dev.tauri.seals package core import java.util.UUID import java.nio.charset.StandardCharsets import scala.language.implicitConversions import scodec.bits.ByteVector final object UUIDUtils { implicit final class UUIDSyntax(private val self: UUID) extends AnyVal { def / (sub: UUID): UUIDBuilder = UUIDBuilder(self) / sub def / (sub: ByteVector): UUIDBuilder = UUIDBuilder(self) / sub def / (sub: String): UUIDBuilder = UUIDBuilder(self) / sub } final case class UUIDBuilder(namespace: UUID, name: Vector[ByteVector] = Vector.empty) { def / (sub: UUID): UUIDBuilder = copy(name = name :+ NsUUID.bvFromUUID(sub)) def / (sub: ByteVector): UUIDBuilder = copy(name = name :+ sub) def / (sub: String): UUIDBuilder = copy(name = name :+ ByteVector.view(sub.getBytes(StandardCharsets.UTF_8))) def uuid: UUID = NsUUID.uuid5nestedBv(namespace, name: _*) } implicit def uuidLiteralSyntax(sc: StringContext): macros.UUIDSyntax = new macros.UUIDSyntax(sc) }
Example 89
Source File: NsUUID.scala From seals with Apache License 2.0 | 5 votes |
package dev.tauri.seals package core import java.util.UUID import java.security.MessageDigest import java.nio.{ ByteBuffer, Buffer } import java.nio.charset.StandardCharsets import scodec.bits.ByteVector private[seals] object NsUUID { def uuid5(ns: UUID, name: String): UUID = uuid5bytes(ns, ByteBuffer.wrap(name.getBytes(StandardCharsets.UTF_8))) def uuid5bv(ns: UUID, name: ByteVector): UUID = uuid5bytes(ns, name.toByteBuffer) private def uuid5bytes(ns: UUID, name: ByteBuffer): UUID = { val buf = ByteBuffer.allocate(16) // network byte order by default putUUIDToBuf(ns, buf) (buf : Buffer).rewind() val h = sha1() h.update(buf) h.update(name) val arr: Array[Byte] = h.digest().take(16) arr(6) = (arr(6) & 0x0f).toByte // clear version arr(6) = (arr(6) | 0x50).toByte // version 5 arr(8) = (arr(8) & 0x3f).toByte // clear variant arr(8) = (arr(8) | 0x80).toByte // variant RFC4122 (buf : Buffer).rewind() buf.put(arr) (buf : Buffer).rewind() val msl = buf.getLong() val lsl = buf.getLong() new UUID(msl, lsl) } def uuid5nested(root: UUID, names: String*): UUID = names.foldLeft(root)(uuid5) def uuid5nestedBv(root: UUID, names: ByteVector*): UUID = { val buf = ByteVector.concat(names).toByteBuffer uuid5bytes(root, buf) } def uuid5nestedNsNm(name: String, ns1: UUID, nss: UUID*): UUID = uuid5(uuid5nestedNs(ns1, nss: _*), name) def uuid5nestedNs(ns1: UUID, nss: UUID*): UUID = { val buf = ByteBuffer.allocate(16) nss.foldLeft(ns1) { (st, u) => putUUIDToBuf(u, buf) (buf : Buffer).rewind() val r = uuid5bytes(st, buf) (buf : Buffer).rewind() r } } private def putUUIDToBuf(u: UUID, buf: ByteBuffer): Unit = { buf.putLong(u.getMostSignificantBits) buf.putLong(u.getLeastSignificantBits) } def bvFromUUID(u: UUID): ByteVector = { val buf = ByteBuffer.allocate(16) putUUIDToBuf(u, buf) (buf : Buffer).rewind() ByteVector.view(buf) } private def sha1(): MessageDigest = MessageDigest.getInstance("SHA-1") }
Example 90
Source File: SignTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.crypto import org.bitcoins.testkit.core.gen.CryptoGenerators import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector import scala.concurrent.{ExecutionContext, Future} class SignTest extends BitcoinSUnitTest { implicit val ec = ExecutionContext.global //ECPrivateKey implements the sign interface //so just use it for testing purposes val signTestImpl = new Sign { private val key = ECPrivateKey.freshPrivateKey override def signFunction: ByteVector => Future[ECDigitalSignature] = { key.signFunction } override def publicKey: ECPublicKey = key.publicKey } behavior of "Sign" it must "sign arbitrary pieces of data correctly" in { forAll(CryptoGenerators.sha256Digest) { case hash: Sha256Digest => val pubKey = signTestImpl.publicKey val sigF = signTestImpl.signFunction(hash.bytes) sigF.map(sig => assert(pubKey.verify(hash.hex, sig))) } } }
Example 91
Source File: HashTypeTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.script.crypto import org.bitcoins.core.number.Int32 import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class HashTypeTest extends BitcoinSUnitTest { "HashType" must "combine hash types with SIGHASH_ANYONECANPAY" in { HashType.sigHashAllAnyoneCanPay.num must be(Int32(0x81)) HashType.sigHashNoneAnyoneCanPay.num must be(Int32(0x82)) HashType.sigHashSingleAnyoneCanPay.num must be(Int32(0x83)) } it must "find a hash type by its hex value" in { HashType("00000001") must be(HashType.sigHashAll) HashType("00000002") must be(HashType.sigHashNone) HashType("00000003") must be(HashType.sigHashSingle) HashType("00000080") must be(HashType.sigHashAnyoneCanPay) } it must "find a hash type by its byte value" in { HashType(0.toByte) must be(SIGHASH_ALL(Int32.zero)) HashType(1.toByte) must be(SIGHASH_ALL(Int32.one)) HashType(2.toByte) must be(HashType.sigHashNone) HashType(3.toByte) must be(HashType.sigHashSingle) HashType(0x80) must be(HashType.sigHashAnyoneCanPay) } it must "default to SIGHASH_ALL if the given string/byte is not known" in { HashType(ByteVector(0x124.toByte)) must be(SIGHASH_ALL(Int32(36))) } it must "find hashType for number 1190874345" in { //1190874345 & 0x80 = 0x80 val num = Int32(1190874345) HashType(num).isInstanceOf[SIGHASH_ANYONECANPAY] must be(true) HashType(num.bytes).isInstanceOf[SIGHASH_ANYONECANPAY] must be(true) } it must "determine if a given number is of hashType SIGHASH_ALL" in { HashType.isSigHashAll(Int32.zero) must be(true) HashType.isSigHashAll(Int32.one) must be(true) HashType.isSigHashAll(Int32(5)) must be(true) HashType.isSigHashAll(HashType.sigHashNone.num) must be(false) HashType.isSigHashAll(HashType.sigHashSingle.num) must be(false) } it must "return the correct byte for a given hashtype" in { SIGHASH_ALL(HashType.sigHashAllByte).byte must be(0x01.toByte) HashType.sigHashNone.byte must be(0x02.toByte) HashType.sigHashSingle.byte must be(0x03.toByte) HashType.sigHashAnyoneCanPay.byte must be(0x80.toByte) HashType.sigHashAllAnyoneCanPay.byte must be(0x81.toByte) HashType.sigHashNoneAnyoneCanPay.byte must be(0x82.toByte) HashType.sigHashSingleAnyoneCanPay.byte must be(0x83.toByte) } it must "intercept require statements for each hashType with illegal inputs" in { intercept[IllegalArgumentException] { SIGHASH_ALL(Int32(2)) } } it must "find each specific hashType from byte sequence of default value" in { //tests each hashtypes overriding fromBytes function HashType(HashType.sigHashAll.num.bytes) must be(HashType.sigHashAll) HashType(HashType.sigHashNone.num.bytes) must be(HashType.sigHashNone) HashType(HashType.sigHashSingle.num.bytes) must be(HashType.sigHashSingle) HashType(HashType.sigHashAnyoneCanPay.num.bytes) must be( HashType.sigHashAnyoneCanPay) HashType(HashType.sigHashAllAnyoneCanPay.num.bytes) must be( HashType.sigHashAllAnyoneCanPay) HashType(HashType.sigHashNoneAnyoneCanPay.num.bytes) must be( HashType.sigHashNoneAnyoneCanPay) HashType(HashType.sigHashSingleAnyoneCanPay.num.bytes) must be( HashType.sigHashSingleAnyoneCanPay) } it must "find a hashtype with only an integer" in { HashType(105512910).isInstanceOf[SIGHASH_ANYONECANPAY] must be(true) } }
Example 92
Source File: ScriptSignatureFactoryTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.script import org.bitcoins.core.util.BytesUtil import org.bitcoins.crypto.{ECDigitalSignature, ECPublicKey} import org.bitcoins.testkit.util.{BitcoinSUnitTest, TestUtil} import scodec.bits.ByteVector class ScriptSignatureFactoryTest extends BitcoinSUnitTest { "ScriptSignatureFactory" must "give the exact same result whether parsing bytes or parsing hex" in { val signatureHex = "30450221008949f0cb400094ad2b5eb399d59d01c14d73d8fe6e96df1a7150deb388ab8935022079656090d7" + "f6bac4c9a94e0aad311a4268e082a725f8aeae0573fb12ff866a5f01" val signatureBytes: ByteVector = BytesUtil.decodeHex(signatureHex) val scriptSigFromHex = ScriptSignature(signatureHex) val scriptSigFromBytes = ScriptSignature(signatureBytes) scriptSigFromHex must be(scriptSigFromBytes) } it must "build a script signature from a digital signature and a public key" in { val digitalSignatureBytes = TestUtil.p2pkhInputScriptAsm(1).bytes val digitalSignature: ECDigitalSignature = ECDigitalSignature(digitalSignatureBytes) val publicKeyBytes = TestUtil.p2pkhInputScriptAsm(3).bytes val publicKey: ECPublicKey = ECPublicKey(publicKeyBytes) val actualScriptSig: ScriptSignature = P2PKHScriptSignature(digitalSignature, publicKey) actualScriptSig.asm must be(TestUtil.p2pkhInputScriptAsm) } it must "parse a p2pk scriptSignature from a raw scriptSig" in { val rawScriptSig = TestUtil.rawP2PKScriptSig val scriptSig = ScriptSignature(rawScriptSig) val result = scriptSig match { case s: P2PKScriptSignature => true case _ => false } result must be(true) } it must "parse a p2sh scriptSignature from a raw scriptSig" in { val result = TestUtil.p2shInputScript2Of2 match { case s: P2SHScriptSignature => true case y => throw new RuntimeException("Should be p2sh input: " + y) } result must be(true) } }
Example 93
Source File: P2PKHScriptSignatureTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.script import org.bitcoins.core.script.crypto.HashType import org.bitcoins.crypto.ECDigitalSignature import org.bitcoins.testkit.util.{BitcoinSUnitTest, TestUtil} import scodec.bits.ByteVector class P2PKHScriptSignatureTest extends BitcoinSUnitTest { "P2PKHScriptSignature" must "be able to identify it's own hash type" in { val p2pkhScriptSig = TestUtil.p2pkhScriptSig match { case s: P2PKHScriptSignature => s case _ => throw new RuntimeException("Must be p2pkh scriptSig") } HashType.fromBytes( ByteVector.fromByte(p2pkhScriptSig.signatures.head.bytes.last)) must be( HashType.sigHashAll) } it must "be able to identify the signature in a p2pkh scriptSig" in { val p2pkhScriptSig = TestUtil.p2pkhScriptSig match { case s: P2PKHScriptSignature => s case _ => throw new RuntimeException("Must be p2pkh scriptSig") } p2pkhScriptSig.signature must be(ECDigitalSignature( "3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01")) } }
Example 94
Source File: UInt64Test.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.number import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class UInt64Test extends BitcoinSUnitTest { "UInt64" must "hold the number 0" in { val uInt64 = UInt64(ByteVector.low(1)) uInt64.hex must be("0000000000000000") uInt64.toBigInt must be(0) } it must "encode the number 1" in { val uInt64 = UInt64(1) uInt64.toBigInt must be(1) uInt64.hex must be("0000000000000001") } it must "hold the max for a uint32_t" in { //this is UInt32_t's max value val uInt64 = UInt64(ByteVector(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte)) uInt64.toBigInt must be(4294967295L) } it must "hold the max for uint32_t + 1" in { val uInt64 = UInt64(ByteVector(1.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte)) uInt64.toBigInt must be(4294967296L) } it must "hold the max number for uint64_t" in { val uInt64 = UInt64( ByteVector(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte)) uInt64.toBigInt must be(BigInt("18446744073709551615")) uInt64.hex must be("ffffffffffffffff") } it must "throw an exception if we try and create a number larger than 8 bytes" in { intercept[IllegalArgumentException] { UInt64( ByteVector(1.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte)) } } it must "have the correct representation for 0" in { UInt64.zero.toBigInt must be(0) } it must "have the correct representation for 1" in { UInt64.one.toBigInt must be(1) } it must "have the correct min number for a UInt64" in { UInt64.min.toBigInt must be(0) } it must "have the correct max number for a UInt64" in { UInt64.max.toBigInt must be(BigInt("18446744073709551615")) } it must "throw an exception if we try to create a BigInt outside the range of UInt64" in { intercept[IllegalArgumentException] { UInt64(UInt64.max.toBigInt + 1) } } }
Example 95
Source File: UInt32Test.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.number import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class UInt32Test extends BitcoinSUnitTest { "UInt32" must "create the number zero as an unsigned 32 bit integer" in { val zero = UInt32(ByteVector(0x0.toByte)) zero.toLong must be(0) } it must "create the max number for an unsigned byte" in { val maxByteValue = UInt32(ByteVector(0xff.toByte)) maxByteValue.toLong must be(255) } it must "create the number 256" in { val uInt32 = UInt32(ByteVector(0x01.toByte, 0x00.toByte)) uInt32.toLong must be(256) } it must "create the number 65535" in { val uInt32 = UInt32(ByteVector(0xff.toByte, 0xff.toByte)) uInt32.toLong must be(65535) } it must "create the number 65536" in { val uInt32 = UInt32(ByteVector(0x01.toByte, 0x0.toByte, 0x0.toByte)) uInt32.toLong must be(65536) } it must "create the number 16777215" in { val uInt32 = UInt32(ByteVector(0xff.toByte, 0xff.toByte, 0xff.toByte)) uInt32.toLong must be(16777215) } it must "create the number 16777216" in { val uInt32 = UInt32(ByteVector(1.toByte, 0.toByte, 0.toByte, 0.toByte)) uInt32.toLong must be(16777216) } it must "create the number 4294967295" in { //this is UInt32_t's max value val uInt32 = UInt32(ByteVector(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte)) uInt32.toLong must be(4294967295L) uInt32.hex must be("ffffffff") } it must "throw an exception if we try and create a UInt32 with a negative number" in { intercept[IllegalArgumentException] { UInt32(-1) } } it must "throw an exception if we try and create a UInt32 with more than 4 bytes" in { intercept[IllegalArgumentException] { UInt32(ByteVector(0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte)) } } it must "have the correct representation for 0" in { UInt32.zero.toLong must be(0) } it must "have the correct representation for 1" in { UInt32.one.toLong must be(1) } it must "have the correct minimum number for a UInt32" in { UInt32.min.toLong must be(0) } it must "have the correct maximum number representation for UInt32" in { UInt32.max.toLong must be(4294967295L) UInt32.max.hex must be("ffffffff") } it must "throw an exception if we try to create a BigInt outside the range of UInt32" in { intercept[IllegalArgumentException] { UInt32(UInt32.max.toBigInt + 1) } } }
Example 96
Source File: Int32Test.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.number import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class Int32Test extends BitcoinSUnitTest { "Int32" must "create the number zero" in { val int32 = Int32(ByteVector.low(1)) int32.toInt must be(0) } it must "represent the number -1" in { val int32 = Int32(ByteVector(0xff.toByte)) int32.toInt must be(-1) } it must "represent the number -1 with 4 bytes" in { val int32 = Int32(ByteVector(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte)) int32.toInt must be(-1) } it must "create the max number for a single byte" in { val int32 = Int32(ByteVector(0x7f.toByte)) int32.toInt must be(127) } it must "create the min number for a single byte" in { val int32 = Int32(ByteVector(0x80.toByte)) int32.toInt must be(-128) } it must "create the max number for an Int32" in { val int32 = Int32(ByteVector(0x7f.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte)) int32.toInt must be(2147483647) } it must "create the minimum number for an Int32" in { val int32 = Int32(ByteVector(0x80.toByte, 0.toByte, 0.toByte, 0.toByte)) int32.toInt must be(-2147483648) } it must "throw an exception if we try and create an Int32 with more than 4 bytes" in { intercept[IllegalArgumentException] { Int32(ByteVector(0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte)) } } it must "have the correct representation for 0" in { Int32.zero.toInt must be(0) } it must "have the correct representation for 1" in { Int32.one.toInt must be(1) } it must "have the correct minimum number representation" in { Int32.min.toInt must be(-2147483648) } it must "have the correct maximum number representation" in { Int32.max.toInt must be(2147483647) } }
Example 97
Source File: UInt8Test.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.number import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class UInt8Test extends BitcoinSUnitTest { "UInt8" must "convert a byte to a UInt8 correctly" in { UInt8.toUInt8(0.toByte) must be(UInt8.zero) UInt8.toUInt8(1.toByte) must be(UInt8.one) UInt8.toUInt8(255.toByte) must be(UInt8(255.toShort)) } it must "throw an exception if we try and create an UInt8 with more than 1 bytes" in { intercept[IllegalArgumentException] { UInt8(ByteVector(0.toByte, 0.toByte)) } } }
Example 98
Source File: FilterTypeTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.gcs import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class FilterTypeTest extends BitcoinSUnitTest { behavior of "FilterType" it must "parse bytes" in { assert(FilterType.fromBytes(ByteVector(0)) == FilterType.Basic) assertThrows[IllegalArgumentException](FilterType.fromBytes(ByteVector(1))) } it must "know its code" in { assert(FilterType.getCode(FilterType.Basic) == 0) assert(FilterType.byCode(0) == FilterType.Basic) assertThrows[IllegalArgumentException](FilterType.byCode(1)) assertThrows[IllegalArgumentException]( FilterType.getCode(FilterType.fromHex("ffff"))) } }
Example 99
Source File: NetworkHeaderTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.p2p import org.bitcoins.core.config.TestNet3 import org.bitcoins.core.number.UInt32 import org.bitcoins.testkit.node.NodeTestUtil import org.bitcoins.testkit.util.BitcoinSUnitTest import org.bitcoins.core.config.MainNet import org.bitcoins.core.util.BytesUtil import org.bitcoins.crypto.CryptoUtil import scala.util.Random import scodec.bits.ByteVector class NetworkHeaderTest extends BitcoinSUnitTest { "MessageHeader" must "must create a message header for a message" in { val messageHeader = NetworkHeader(TestNet3, NodeTestUtil.versionMessage) messageHeader.network must be(TestNet3) messageHeader.commandName must be(NodeTestUtil.versionMessage.commandName) messageHeader.payloadSize must be( UInt32(NodeTestUtil.versionMessage.bytes.size)) messageHeader.checksum must be( CryptoUtil.doubleSHA256(NodeTestUtil.versionMessage.bytes).bytes.take(4)) } it must "build the correct message header for a verack message" in { val messageHeader = NetworkHeader(TestNet3, VerAckMessage) messageHeader.network must be(TestNet3) messageHeader.commandName must be(VerAckMessage.commandName) messageHeader.payloadSize must be(UInt32.zero) BytesUtil.encodeHex(messageHeader.checksum) must be("5df6e0e2") } it must "throw on messages of bad length" in { intercept[IllegalArgumentException] { val commandName = Random.shuffle(NetworkPayload.commandNames).head NetworkHeader(MainNet, commandName, payloadSize = UInt32.one, checksum = ByteVector.empty) } } }
Example 100
Source File: RawScriptPubKeyParserTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.script import org.bitcoins.core.protocol.script.{EmptyScriptPubKey, ScriptPubKey} import org.bitcoins.core.script.bitwise.OP_EQUALVERIFY import org.bitcoins.core.script.constant._ import org.bitcoins.core.script.crypto.{OP_CHECKSIG, OP_HASH160} import org.bitcoins.core.script.stack.OP_DUP import org.bitcoins.core.util.BytesUtil import org.bitcoins.testkit.util.{BitcoinSUnitTest, TestUtil} import scodec.bits.ByteVector class RawScriptPubKeyParserTest extends BitcoinSUnitTest { val encode = BytesUtil.encodeHex(_: ByteVector) "RawScriptPubKeyParser" must "read then write the scriptPubKey and get the original scriptPubKey" in { val scriptPubKey: ScriptPubKey = RawScriptPubKeyParser.read(TestUtil.rawScriptPubKey) encode(RawScriptPubKeyParser.write(scriptPubKey)) must be( TestUtil.rawScriptPubKey) } it must "read an EmptyScriptPubKey" in { assert(RawScriptPubKeyParser.read(ByteVector.empty) == EmptyScriptPubKey) } it must "read a raw scriptPubKey and give us the expected asm" in { val scriptPubKey = RawScriptPubKeyParser.read(TestUtil.rawP2PKHScriptPubKey) val expectedAsm: Seq[ScriptToken] = List(OP_DUP, OP_HASH160, BytesToPushOntoStack(20), ScriptConstant("31a420903c05a0a7de2de40c9f02ebedbacdc172"), OP_EQUALVERIFY, OP_CHECKSIG) scriptPubKey.asm must be(expectedAsm) } it must "read a raw scriptPubKey from an output" in { //from b30d3148927f620f5b1228ba941c211fdabdae75d0ba0b688a58accbf018f3cc //output is index 1 val rawScriptPubKey = "17a914af575bd77c5ce7eba3bd9ce6f89774713ae62c7987" val scriptPubKey = RawScriptPubKeyParser.read(rawScriptPubKey) encode(RawScriptPubKeyParser.write(scriptPubKey)) must be(rawScriptPubKey) } it must "read and write the scriptPubKey that pushes using a PUSHDATA1 that is negative when read as signed" in { val rawScriptPubKey = "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG" val asm = ScriptParser.fromString(rawScriptPubKey) val scriptPubKey = ScriptPubKey.fromAsm(asm) val actualRawScriptPubKey = RawScriptPubKeyParser.write(scriptPubKey) //the actual hex representation is from a bitcoin core test case inside of tx_valid.json encode(actualRawScriptPubKey) must be( "ca4cae606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e2074607576a914bfd7436b6265aa9de506f8a994f881ff08cc287288ac") } }
Example 101
Source File: RawTransactionOutputParserTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.transaction import org.bitcoins.core.currency.Satoshis import org.bitcoins.core.number.Int64 import org.bitcoins.core.protocol.transaction.{ EmptyTransactionOutput, TransactionOutput } import org.bitcoins.core.script.bitwise.OP_EQUAL import org.bitcoins.core.script.constant.{BytesToPushOntoStack, ScriptConstant} import org.bitcoins.core.script.crypto.OP_HASH160 import org.bitcoins.core.util.BytesUtil import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class RawTransactionOutputParserTest extends BitcoinSUnitTest { //txid cad1082e674a7bd3bc9ab1bc7804ba8a57523607c876b8eb2cbe645f2b1803d6 val rawTxOutput = "204e00000000000017a914eda8ae08b5c9f973f49543e90a7c292367b3337c87" val encode = BytesUtil.encodeHex(_: ByteVector) "RawTransactionOutputTest" must "read a serialized tx output" in { val txOutput: TransactionOutput = RawTransactionOutputParser.read(rawTxOutput) txOutput.value must be(Satoshis(20000)) txOutput.scriptPubKey.asm must be( Seq(OP_HASH160, BytesToPushOntoStack(20), ScriptConstant("eda8ae08b5c9f973f49543e90a7c292367b3337c"), OP_EQUAL)) } it must "seralialize a transaction output" in { val txOutput = RawTransactionOutputParser.read(rawTxOutput) encode(RawTransactionOutputParser.write(txOutput)) must be(rawTxOutput) } it must "serialize a single transaction output not in a sequence" in { val txOutput = RawTransactionOutputParser.read(rawTxOutput) encode(RawTransactionOutputParser.write(txOutput)) must be(rawTxOutput) } it must "serialize an older raw transaction output" in { //from this question //https://bitcoin.stackexchange.com/questions/2859/how-are-transaction-hashes-calculated val txOutput = "00f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac" val output = RawTransactionOutputParser.read(txOutput) output.value must be(Satoshis(5000000000L)) } it must "serialize the empty transaction output correctly" in { encode(RawTransactionOutputParser.write(EmptyTransactionOutput)) must be( "ffffffffffffffff00") } }
Example 102
Source File: RawTransactionOutPointParserTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.transaction import org.bitcoins.core.number.UInt32 import org.bitcoins.core.util.BytesUtil import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class RawTransactionOutPointParserTest extends BitcoinSUnitTest { //txid cad1082e674a7bd3bc9ab1bc7804ba8a57523607c876b8eb2cbe645f2b1803d6 val rawOutPoint = "85d6b0da2edf96b282030d3f4f79d14cc8c882cfef1b3064170c850660317de100000000" val rawOutPointLargeVout = "df80e3e6eba7dcd4650281d3c13f140dafbb823a7227a78eb6ee9f6cedd0400134000000" val encode = BytesUtil.encodeHex(_: ByteVector) "RawTransactionOutPointParser" must "read a raw outpoint into a native scala TransactionOutPoint" in { val outPoint = RawTransactionOutPointParser.read(rawOutPoint) outPoint.txId.hex must be( BytesUtil.flipEndianness( "e17d316006850c1764301befcf82c8c84cd1794f3f0d0382b296df2edab0d685")) outPoint.vout must be(UInt32.zero) } it must "parse a large vout for an outpoint" in { val outPoint = RawTransactionOutPointParser.read(rawOutPointLargeVout) outPoint.vout must be(UInt32(52)) outPoint.txId.hex must be( BytesUtil.flipEndianness( "0140d0ed6c9feeb68ea727723a82bbaf0d143fc1d3810265d4dca7ebe6e380df")) } it must "write a TransactionOutPoint to a serialized format" in { val outPoint = RawTransactionOutPointParser.read(rawOutPoint) val actualSerialization = RawTransactionOutPointParser.write(outPoint) encode(actualSerialization) must be(rawOutPoint) } it must "write a outpoint that has a large vout" in { val outPoint = RawTransactionOutPointParser.read(rawOutPointLargeVout) val serializedOutpoint = RawTransactionOutPointParser.write(outPoint) encode(serializedOutpoint) must be(rawOutPointLargeVout) } it must "write this outpoint with vout index 1" in { //from txid bdc221db675c06dbee2ae75d33e31cad4e2555efea10c337ff32c8cdf97f8e74 val rawOutPoint = "fc37adbd036fb51b3f4f6f70474270939d6ff8c4ea697639f2b57dd6359e307001000000" val outPoint = RawTransactionOutPointParser.read(rawOutPoint) outPoint.txId.hex must be( BytesUtil.flipEndianness( "70309e35d67db5f2397669eac4f86f9d93704247706f4f3f1bb56f03bdad37fc")) val serializedOutPoint = RawTransactionOutPointParser.write(outPoint) encode(serializedOutPoint) must be(rawOutPoint) } it must "determine the correct size of a transaction outpoint" in { //cad1082e674a7bd3bc9ab1bc7804ba8a57523607c876b8eb2cbe645f2b1803d6 val rawOutPoint = "85d6b0da2edf96b282030d3f4f79d14cc8c882cfef1b3064170c850660317de100000000" val outPoint = RawTransactionOutPointParser.read(rawOutPoint) outPoint.byteSize must be(36) } it must "parse a outpoint with extremely large vout" in { //vout should be 20183580 val rawOutPoint = "4435c4ea162d51135c9b2bbb867a86f25001c246224b60e8ab2307edce7fc28a0ca13f13" val outPoint = RawTransactionOutPointParser.read(rawOutPoint) outPoint.vout must be(UInt32(322937100)) outPoint.hex must be(rawOutPoint) } }
Example 103
Source File: RawBitcoinSerializerHelperTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers import org.bitcoins.core.number.UInt64 import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.protocol.transaction.{ EmptyTransactionOutput, TransactionInput, TransactionOutput } import org.bitcoins.core.serializers.transaction.{ RawTransactionInputParser, RawTransactionOutputParser } import org.bitcoins.testkit.util.BitcoinSUnitTest import scodec.bits.ByteVector class RawSerializerHelperTest extends BitcoinSUnitTest { "RawBitcoinSerializerHelper" must "serialize an empty vector" in { val bytes = ByteVector(0.toByte) val construct: ByteVector => TransactionInput = RawTransactionInputParser.read(_) val (inputs, _) = RawSerializerHelper.parseCmpctSizeUIntSeq(bytes, construct) val serialize = RawTransactionInputParser.write(_) val write = RawSerializerHelper.writeCmpctSizeUInt(inputs, serialize) write must be(bytes) } it must "serialize one element in a vector correctly" in { val bytes = CompactSizeUInt(UInt64.one).bytes ++ EmptyTransactionOutput.bytes val constructor: ByteVector => TransactionOutput = RawTransactionOutputParser.read(_) val (outputs, _) = RawSerializerHelper.parseCmpctSizeUIntSeq(bytes, constructor) val serialize = RawTransactionOutputParser.write(_) val write = RawSerializerHelper.writeCmpctSizeUInt(outputs, serialize) write must be(bytes) } }
Example 104
Source File: RawSerializerHelperSpec.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers import org.bitcoins.testkit.core.gen.TransactionGenerators import org.bitcoins.core.protocol.transaction.TransactionOutput import org.scalacheck.{Prop, Properties} import scodec.bits.ByteVector class RawSerializerHelperSpec extends Properties("RawSerializerHelperSpec") { property("serialization symmetry of txs") = { Prop.forAll(TransactionGenerators.smallOutputs) { txs: Seq[TransactionOutput] => val serialized = RawSerializerHelper.writeCmpctSizeUInt(txs, { tx: TransactionOutput => tx.bytes }) val (deserialized, remaining) = RawSerializerHelper .parseCmpctSizeUIntSeq(serialized, TransactionOutput(_: ByteVector)) deserialized == txs && remaining == ByteVector.empty } } }
Example 105
Source File: ZMQSubscriberTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.zmq import java.net.InetSocketAddress import org.bitcoins.core.util.BytesUtil import org.scalatest.flatspec.AsyncFlatSpec import org.slf4j.LoggerFactory import org.zeromq.{ZFrame, ZMQ, ZMsg} import scodec.bits.ByteVector import scala.concurrent.Promise class ZMQSubscriberTest extends AsyncFlatSpec { private val logger = LoggerFactory.getLogger(this.getClass().toString) behavior of "ZMQSubscriber" it must "connect to a regtest instance of a daemon and stream txs/blocks from it" in { //note for this unit test to pass, you need to setup a bitcoind instance yourself //and set the bitcoin.conf file to allow for //zmq connections //see: https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md val socket = new InetSocketAddress("tcp://127.0.0.1", 29000) val zmqSub = new ZMQSubscriber(socket, None, None, rawTxListener, rawBlockListener) //stupid, doesn't test anything, for now. You need to look at log output to verify this is working // TODO: In the future this could use the testkit to verify the subscriber by calling generate(1) zmqSub.start() Thread.sleep(10000) // 10 seconds zmqSub.stop succeed } it must "be able to subscribe to a publisher and read a value" in { val port = Math.abs(scala.util.Random.nextInt % 14000) + 1000 val socket = new InetSocketAddress("tcp://127.0.0.1", port) val context = ZMQ.context(1) val publisher = context.socket(ZMQ.PUB) val uri = socket.getHostString + ":" + socket.getPort publisher.bind(uri) val valuePromise = Promise[String]() val fakeBlockListener: Option[ByteVector => Unit] = Some { bytes => val str = new String(bytes.toArray) valuePromise.success(str) () } val sub = new ZMQSubscriber(socket, None, None, None, fakeBlockListener) sub.start() Thread.sleep(1000) val testValue = "sweet, sweet satoshis" val msg = new ZMsg() msg.add(new ZFrame(RawBlock.topic)) msg.add(new ZFrame(testValue)) val sent = msg.send(publisher) assert(sent) valuePromise.future.map { str => sub.stop publisher.close() context.term() assert(str == testValue) } } val rawBlockListener: Option[ByteVector => Unit] = Some { { bytes: ByteVector => val hex = BytesUtil.encodeHex(bytes) logger.debug(s"received raw block ${hex}") } } val hashBlockListener: Option[ByteVector => Unit] = Some { { bytes: ByteVector => val hex = BytesUtil.encodeHex(bytes) logger.debug(s"received raw block hash ${hex}") } } val rawTxListener: Option[ByteVector => Unit] = Some { { bytes: ByteVector => val hex = BytesUtil.encodeHex(bytes) logger.debug(s"received raw tx ${hex}") } } }
Example 106
Source File: InitOracleDialog.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.gui.dlc.dialog import org.bitcoins.commons.jsonmodels.dlc.DLCMessage.ContractInfo import org.bitcoins.core.currency.Satoshis import org.bitcoins.crypto.CryptoUtil import scalafx.Includes._ import scalafx.application.Platform import scalafx.geometry.Insets import scalafx.scene.control.{ButtonType, Dialog, Label, TextField} import scalafx.scene.layout.GridPane import scalafx.stage.Window import scodec.bits.ByteVector object InitOracleDialog { def showAndWait( parentWindow: Window, numOutcomes: Int): Option[(Vector[String], ContractInfo)] = { val dialog = new Dialog[Option[(Vector[String], ContractInfo)]]() { initOwner(parentWindow) title = "Initialize Demo Oracle" headerText = "Enter contract outcomes and their outcome values" } val fields = (0 until numOutcomes).map(_ => (new TextField(), new TextField() { promptText = "Satoshis" })) dialog.dialogPane().buttonTypes = Seq(ButtonType.OK, ButtonType.Cancel) dialog.dialogPane().content = new GridPane { hgap = 10 vgap = 10 padding = Insets(20, 100, 10, 10) add(new Label("Outcomes"), 0, 0) add(new Label("Values"), 1, 0) var nextRow: Int = 1 fields.foreach { case (str, value) => add(str, 0, nextRow) add(value, 1, nextRow) nextRow += 1 } } // Enable/Disable OK button depending on whether all data was entered. val okButton = dialog.dialogPane().lookupButton(ButtonType.OK) // Simple validation that sufficient data was entered okButton.disable <== fields .map { case (str, value) => str.text.isEmpty || value.text.isEmpty } .reduce(_ || _) // Request focus on the first field by default. Platform.runLater(fields.head._1.requestFocus()) // When the OK button is clicked, convert the result to a CreateDLCOffer. dialog.resultConverter = dialogButton => if (dialogButton == ButtonType.OK) { val inputs = fields.map { case (str, value) => (str.text(), value.text()) } val contractMap = inputs.map { case (str, value) => val hash = CryptoUtil.sha256(ByteVector(str.getBytes)).flip hash -> Satoshis(BigInt(value)) }.toMap val outcomes = inputs.map(_._1).toVector Some((outcomes, ContractInfo(contractMap))) } else None val result = dialog.showAndWait() result match { case Some(Some((outcomes: Vector[_], contractInfo: ContractInfo))) => Some((outcomes.map(_.toString), contractInfo)) case Some(_) | None => None } } }
Example 107
Source File: DLCMessageTest.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.commons.dlc import org.bitcoins.commons.jsonmodels.dlc.DLCMessage.{ ContractInfo, DLCAccept, DLCOffer, OracleInfo } import org.bitcoins.commons.jsonmodels.dlc.{ CETSignatures, DLCPublicKeys, DLCTimeouts } import org.bitcoins.core.currency.Satoshis import org.bitcoins.core.number.UInt32 import org.bitcoins.core.protocol.BitcoinAddress import org.bitcoins.core.protocol.BlockStamp.{BlockHeight, BlockTime} import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte import org.bitcoins.crypto.{ DummyECDigitalSignature, ECPublicKey, Sha256DigestBE } import org.bitcoins.testkit.util.BitcoinSAsyncTest import scodec.bits.ByteVector class DLCMessageTest extends BitcoinSAsyncTest { behavior of "DLCMessage" it must "not allow a DLCTimeout where the contract times out before it matures" in { assertThrows[IllegalArgumentException]( DLCTimeouts(UInt32(5), BlockHeight(4), BlockHeight(2))) assertThrows[IllegalArgumentException]( DLCTimeouts(UInt32(5), BlockTime(UInt32(4)), BlockTime(UInt32(2)))) } val dummyPubKey: ECPublicKey = ECPublicKey.freshPublicKey val dummyPubKey2: ECPublicKey = ECPublicKey.freshPublicKey val dummyAddress: BitcoinAddress = BitcoinAddress( "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa") val dummyHash: Sha256DigestBE = Sha256DigestBE( "00000000000000000008bba30d4d0fb53dcbffb601557de9f16d257d4f1985b7") val dummySig: PartialSignature = PartialSignature(dummyPubKey, DummyECDigitalSignature) it must "not allow a negative collateral for a DLCOffer" in { assertThrows[IllegalArgumentException]( DLCOffer( ContractInfo.empty, OracleInfo.dummy, DLCPublicKeys(dummyPubKey, dummyPubKey2, dummyAddress), Satoshis(-1), Vector.empty, dummyAddress, SatoshisPerVirtualByte.one, DLCTimeouts(UInt32(5), BlockHeight(1), BlockHeight(2)) )) } it must "not allow a negative collateral for a DLCAccept" in { assertThrows[IllegalArgumentException]( DLCAccept( Satoshis(-1), DLCPublicKeys(dummyPubKey, dummyPubKey2, dummyAddress), Vector.empty, dummyAddress, CETSignatures(Map(dummyHash -> dummySig), dummySig), Sha256DigestBE(ByteVector.low(32)) ) ) } it must "not allow duplicate keys in a DLCPublicKeys" in { assertThrows[IllegalArgumentException]( DLCPublicKeys(dummyPubKey, dummyPubKey, dummyAddress) ) } }
Example 108
Source File: SchnorrNonce.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.crypto import scodec.bits.ByteVector import scala.annotation.tailrec import scala.util.Try case class SchnorrNonce(bytes: ByteVector) extends NetworkElement { require(bytes.length == 32, s"Schnorr nonce must be 32 bytes, get $bytes") private val evenKey: ECPublicKey = ECPublicKey(s"02$hex") private val oddKey: ECPublicKey = ECPublicKey(s"03$hex") private val yCoordEven: Boolean = { evenKey.toPoint.getRawYCoord.sqrt() != null } def fromBipSchnorr( privKey: ECPrivateKey, message: ByteVector, auxRand: ByteVector): SchnorrNonce = { val k = kFromBipSchnorr(privKey, message, auxRand) k.publicKey.schnorrNonce } def apply(xCoor: FieldElement): SchnorrNonce = { SchnorrNonce(xCoor.bytes) } }
Example 109
Source File: PBKDF2.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.crypto import javax.crypto.spec.PBEKeySpec import javax.crypto.{SecretKey, SecretKeyFactory} import scodec.bits.ByteVector def withSha512( bytes: ByteVector, salt: ByteVector, iterationCount: Int, derivedKeyLength: Int): SecretKey = { val keySpec = new PBEKeySpec( bytes.toArray.map(_.toChar), salt.toArray, iterationCount, derivedKeyLength ) secretKeyFactory.generateSecret(keySpec) } }
Example 110
Source File: SchnorrDigitalSignature.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.crypto import scodec.bits.ByteVector case class SchnorrDigitalSignature(rx: SchnorrNonce, sig: FieldElement) extends NetworkElement { override def bytes: ByteVector = rx.bytes ++ sig.bytes } object SchnorrDigitalSignature extends Factory[SchnorrDigitalSignature] { override def fromBytes(bytes: ByteVector): SchnorrDigitalSignature = { require(bytes.length == 64, s"SchnorrDigitalSignature must be exactly 64 bytes, got $bytes") SchnorrDigitalSignature(SchnorrNonce(bytes.take(32)), FieldElement(bytes.drop(32))) } }
Example 111
Source File: SchnorrPublicKey.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.crypto import org.bitcoin.NativeSecp256k1 import scodec.bits.ByteVector import scala.annotation.tailrec import scala.util.Try case class SchnorrPublicKey(bytes: ByteVector) extends NetworkElement { require(bytes.length == 32, s"Schnorr public keys must be 32 bytes, got $bytes") require(Try(publicKey).isSuccess, s"Schnorr public key must be a valid x coordinate, got $bytes") // TODO: match on CryptoContext once secp version is added def verify(data: ByteVector, signature: SchnorrDigitalSignature): Boolean = { verifyWithBouncyCastle(data, signature) } def computeSigPointWithBouncyCastle( data: ByteVector, nonce: SchnorrNonce, compressed: Boolean = true): ECPublicKey = { BouncyCastleUtil.schnorrComputeSigPoint(data, nonce, this, compressed) } def publicKey: ECPublicKey = { val pubKeyBytes = ByteVector.fromByte(2) ++ bytes val validPubKey = CryptoContext.default match { case CryptoContext.LibSecp256k1 => NativeSecp256k1.isValidPubKey(pubKeyBytes.toArray) case CryptoContext.BouncyCastle => BouncyCastleUtil.validatePublicKey(pubKeyBytes) } require( validPubKey, s"Cannot construct schnorr public key from invalid x coordinate: $bytes") ECPublicKey(pubKeyBytes) } def xCoord: FieldElement = FieldElement(bytes) } object SchnorrPublicKey extends Factory[SchnorrPublicKey] { @tailrec def fromBytes(bytes: ByteVector): SchnorrPublicKey = { require(bytes.length <= 33, s"XOnlyPublicKey must be less than 33 bytes, got $bytes") if (bytes.length == 32) new SchnorrPublicKey(bytes) else if (bytes.length < 32) { // means we need to pad the private key with 0 bytes so we have 32 bytes SchnorrPublicKey.fromBytes(bytes.padLeft(32)) } else if (bytes.length == 33) { // this is for the case when java serialies a BigInteger to 33 bytes to hold the signed num representation SchnorrPublicKey.fromBytes(bytes.tail) } else { throw new IllegalArgumentException( "XOnlyPublicKey cannot be greater than 33 bytes in size, got: " + CryptoBytesUtil.encodeHex(bytes) + " which is of size: " + bytes.size) } } def apply(xCoor: FieldElement): SchnorrPublicKey = { SchnorrPublicKey(xCoor.bytes) } }
Example 112
Source File: CompactFilterDb.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.chain.models import org.bitcoins.core.gcs.{BlockFilter, FilterType, GolombFilter} import org.bitcoins.crypto.{CryptoUtil, DoubleSha256DigestBE} import scodec.bits.ByteVector case class CompactFilterDb( hashBE: DoubleSha256DigestBE, filterType: FilterType, bytes: ByteVector, height: Int, blockHashBE: DoubleSha256DigestBE) { require( CryptoUtil.doubleSHA256(bytes).flip == hashBE, s"Bytes must hash to hashBE! It looks like you didn't construct CompactFilterDb correctly") def golombFilter: GolombFilter = filterType match { case FilterType.Basic => BlockFilter.fromBytes(bytes, blockHashBE.flip) } override def toString: String = { s"CompactFilterDb(hashBE=$hashBE,filterType=$filterType,height=$height,blockHashBE=$blockHashBE,bytes=${bytes})" } } object CompactFilterDbHelper { def fromGolombFilter( golombFilter: GolombFilter, blockHash: DoubleSha256DigestBE, height: Int): CompactFilterDb = fromFilterBytes(golombFilter.bytes, blockHash, height) def fromFilterBytes( filterBytes: ByteVector, blockHash: DoubleSha256DigestBE, height: Int): CompactFilterDb = CompactFilterDb(CryptoUtil.doubleSHA256(filterBytes).flip, FilterType.Basic, filterBytes, height, blockHash) }
Example 113
Source File: CompactFilterDAO.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.chain.models import org.bitcoins.chain.config.ChainAppConfig import org.bitcoins.core.gcs.FilterType import org.bitcoins.crypto.DoubleSha256DigestBE import org.bitcoins.db.{CRUD, SlickUtil} import scodec.bits.ByteVector import scala.concurrent.{ExecutionContext, Future} case class CompactFilterDAO()(implicit ec: ExecutionContext, override val appConfig: ChainAppConfig) extends CRUD[CompactFilterDb, DoubleSha256DigestBE] with SlickUtil[CompactFilterDb, DoubleSha256DigestBE] { val mappers = new org.bitcoins.db.DbCommonsColumnMappers(profile) import mappers.{ byteVectorMapper, doubleSha256DigestBEMapper, filterTypeMapper } import profile.api._ implicit private val bigIntMapper: BaseColumnType[BigInt] = if (appConfig.driverName == "postgresql") { mappers.bigIntPostgresMapper } else { mappers.bigIntMapper } class CompactFilterTable(tag: Tag) extends Table[CompactFilterDb](tag, "cfilters") { def hash = column[DoubleSha256DigestBE]("hash") def filterType = column[FilterType]("filter_type") def bytes = column[ByteVector]("bytes") def height = column[Int]("height") def blockHash = column[DoubleSha256DigestBE]("block_hash", O.PrimaryKey) def heightIndex = index("cfilters_height_index", height) def hashIndex = index("cfilters_hash_index", hash) override def * = { (hash, filterType, bytes, height, blockHash) <> (CompactFilterDb.tupled, CompactFilterDb.unapply) } } override val table: profile.api.TableQuery[CompactFilterTable] = { TableQuery[CompactFilterTable] } private lazy val blockHeaderTable: profile.api.TableQuery[ BlockHeaderDAO#BlockHeaderTable] = { BlockHeaderDAO().table } override def createAll( filters: Vector[CompactFilterDb]): Future[Vector[CompactFilterDb]] = { createAllNoAutoInc(ts = filters, database = safeDatabase) } def getBestFilter: Future[Option[CompactFilterDb]] = { val join = (table .join(blockHeaderTable)) .on(_.blockHash === _.hash) val query = join.groupBy(_._1).map { case (filter, headers) => filter -> headers.map(_._2.chainWork).max } val filtersWithWorkF: Future[Vector[(CompactFilterDb, Option[BigInt])]] = { safeDatabase.runVec(query.result) } filtersWithWorkF.map { filtersWithWork => if (filtersWithWork.isEmpty) { None } else { val highest = filtersWithWork.maxBy(_._2.getOrElse(BigInt(0)))._1 Some(highest) } } } }
Example 114
Source File: DLCTimeouts.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.commons.jsonmodels.dlc import org.bitcoins.core.number.UInt32 import org.bitcoins.core.protocol.BlockStamp.{BlockHeight, BlockTime} import org.bitcoins.core.protocol.BlockTimeStamp import org.bitcoins.crypto.{Factory, NetworkElement} import scodec.bits.ByteVector final val DEFAULT_PENALTY_TIMEOUT: UInt32 = UInt32(5) override def fromBytes(bytes: ByteVector): DLCTimeouts = { require(bytes.size == 12, s"A DLCTimeouts is exactly 12 bytes, got $bytes") val penalty = UInt32(bytes.take(4)) val contractMaturity = BlockTimeStamp.fromUInt32(UInt32(bytes.slice(4, 8))) val contractTimeout = BlockTimeStamp.fromUInt32(UInt32(bytes.takeRight(4))) DLCTimeouts(penalty, contractMaturity, contractTimeout) } }
Example 115
Source File: EncryptedMnemonic.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.keymanager import java.time.Instant import org.bitcoins.core.compat.CompatEither import org.bitcoins.core.crypto._ import org.bitcoins.crypto.{AesCrypt, AesEncryptedData, AesPassword, AesSalt} import scodec.bits.ByteVector import scala.util.{Failure, Success, Try} case class DecryptedMnemonic( mnemonicCode: MnemonicCode, creationTime: Instant) { def encrypt(password: AesPassword): EncryptedMnemonic = EncryptedMnemonicHelper.encrypt(this, password) } case class EncryptedMnemonic( value: AesEncryptedData, salt: AesSalt, creationTime: Instant) { def toMnemonic(password: AesPassword): Try[MnemonicCode] = { val key = password.toKey(salt) val either = AesCrypt.decrypt(value, key) CompatEither(either).toTry.flatMap { decrypted => decrypted.decodeUtf8 match { case Left(_) => // when failing to decode this to a UTF-8 string // we assume it's because of a bad password Failure(ReadMnemonicError.DecryptionError) case Right(wordsStr) => val wordsVec = wordsStr.split(" ").toVector Success(MnemonicCode.fromWords(wordsVec)) } } } } object EncryptedMnemonicHelper { def encrypt( mnemonic: DecryptedMnemonic, password: AesPassword): EncryptedMnemonic = { val wordsStr = mnemonic.mnemonicCode.words.mkString(" ") val Right(clearText) = ByteVector.encodeUtf8(wordsStr) val (key, salt) = password.toKey val encryted = AesCrypt .encrypt(clearText, key) EncryptedMnemonic(encryted, salt, mnemonic.creationTime) } }
Example 116
Source File: BroadcastAbleTransactionDAO.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.node.models import org.bitcoins.db.CRUDAutoInc import org.bitcoins.node.config.NodeAppConfig import scala.concurrent.ExecutionContext import slick.lifted.ProvenShape import scala.concurrent.Future import org.bitcoins.core.protocol.transaction.Transaction import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE} import scodec.bits.ByteVector final case class BroadcastAbleTransactionDAO()(implicit override val appConfig: NodeAppConfig, val ec: ExecutionContext) extends CRUDAutoInc[BroadcastAbleTransaction] { import profile.api._ val mappers = new org.bitcoins.db.DbCommonsColumnMappers(profile) import mappers._ override val table: profile.api.TableQuery[BroadcastAbleTransactionTable] = profile.api.TableQuery[BroadcastAbleTransactionTable] class BroadcastAbleTransactionTable(tag: Tag) extends TableAutoInc[BroadcastAbleTransaction](tag, "broadcast_elements") { private type Tuple = (DoubleSha256DigestBE, ByteVector, Option[Long]) private val fromTuple: (Tuple => BroadcastAbleTransaction) = { case (txid, bytes, id) => val tx = Transaction.fromBytes(bytes) require(tx.txId == txid.flip) BroadcastAbleTransaction(tx, id) } private val toTuple: BroadcastAbleTransaction => Option[Tuple] = tx => Some(tx.transaction.txId.flip, tx.transaction.bytes, tx.id) def txid: Rep[DoubleSha256DigestBE] = column("txid", O.Unique) def bytes: Rep[ByteVector] = column("tx_bytes") def * : ProvenShape[BroadcastAbleTransaction] = (txid, bytes, id.?) <> (fromTuple, toTuple) } }
Example 117
Source File: ScriptOperationFactory.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.script import org.bitcoins.core.script.arithmetic.ArithmeticOperation import org.bitcoins.core.script.bitwise.BitwiseOperation import org.bitcoins.core.script.constant._ import org.bitcoins.core.script.control.ControlOperations import org.bitcoins.core.script.crypto.CryptoOperation import org.bitcoins.core.script.locktime.LocktimeOperation import org.bitcoins.core.script.reserved.ReservedOperation import org.bitcoins.core.script.splice.SpliceOperation import org.bitcoins.core.script.stack.StackOperation import org.bitcoins.core.util.{BitcoinSLogger, BytesUtil} import scodec.bits.ByteVector final override val operations: Vector[ScriptOperation] = { StackPushOperationFactory.pushDataOperations ++ StackOperation.operations ++ LocktimeOperation.operations ++ CryptoOperation.operations ++ ControlOperations.operations ++ BitwiseOperation.operations ++ ArithmeticOperation.operations ++ BytesToPushOntoStack.operations ++ SpliceOperation.operations ++ ReservedOperation.operations ++ ScriptNumberOperation.operations } }
Example 118
Source File: PaymentSecret.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.ln import org.bitcoins.crypto.{ CryptoUtil, ECPrivateKey, Factory, NetworkElement, Sha256Digest } import scodec.bits.ByteVector final case class PaymentSecret(bytes: ByteVector) extends NetworkElement { require(bytes.size == 32, s"Payment secret must be 32 bytes in size, got: " + bytes.length) lazy val hash: Sha256Digest = CryptoUtil.sha256(bytes) } object PaymentSecret extends Factory[PaymentSecret] { override def fromBytes(bytes: ByteVector): PaymentSecret = { new PaymentSecret(bytes) } def random: PaymentSecret = fromBytes(ECPrivateKey.freshPrivateKey.bytes) }
Example 119
Source File: ShortChannelId.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.ln import org.bitcoins.core.number.UInt64 import org.bitcoins.crypto.{Factory, NetworkElement} import scodec.bits.ByteVector case class ShortChannelId(u64: UInt64) extends NetworkElement { override def bytes: ByteVector = u64.bytes def toHumanReadableString: String = { val blockHeight = (u64 >> 40) & UInt64(0xffffff) val txIndex = (u64 >> 16) & UInt64(0xffffff) val outputIndex = u64 & UInt64(0xffff) s"${blockHeight.toInt}x${txIndex.toInt}x${outputIndex.toInt}" } } object ShortChannelId extends Factory[ShortChannelId] { override def fromBytes(byteVector: ByteVector): ShortChannelId = { new ShortChannelId(UInt64.fromBytes(byteVector)) } def fromHumanReadableString(str: String): ShortChannelId = str.split("x") match { case Array(_blockHeight, _txIndex, _outputIndex) => val blockHeight = BigInt(_blockHeight) require(blockHeight >= 0 && blockHeight <= 0xffffff, "ShortChannelId: invalid block height") val txIndex = _txIndex.toInt require(txIndex >= 0 && txIndex <= 0xffffff, "ShortChannelId:invalid tx index") val outputIndex = _outputIndex.toInt require(outputIndex >= 0 && outputIndex <= 0xffff, "ShortChannelId: invalid output index") val u64 = UInt64( ((blockHeight & 0xffffffL) << 40) | ((txIndex & 0xffffffL) << 16) | (outputIndex & 0xffffL)) ShortChannelId(u64) case _: Array[String] => fromHex(str) } }
Example 120
Source File: LnRoute.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.ln.routing import java.math.BigInteger import org.bitcoins.core.number.UInt32 import org.bitcoins.core.protocol.ln.ShortChannelId import org.bitcoins.core.protocol.ln.currency.MilliSatoshis import org.bitcoins.core.protocol.ln.fee.{ FeeBaseMSat, FeeProportionalMillionths } import org.bitcoins.core.util.BytesUtil import org.bitcoins.crypto.{ECPublicKey, NetworkElement} import scodec.bits.ByteVector case class LnRoute( pubkey: ECPublicKey, shortChannelID: ShortChannelId, feeBaseMsat: FeeBaseMSat, feePropMilli: FeeProportionalMillionths, cltvExpiryDelta: Short) extends NetworkElement { require(pubkey.isCompressed, s"Can only use a compressed public key in routing") override def bytes: ByteVector = { val cltvExpiryDeltaHex = BytesUtil.encodeHex(cltvExpiryDelta) pubkey.bytes ++ shortChannelID.bytes ++ feeBaseMsat.bytes ++ feePropMilli.bytes ++ ByteVector.fromValidHex(cltvExpiryDeltaHex) } } object LnRoute { def fromBytes(bytes: ByteVector): LnRoute = { val PUBKEY_LEN = 33 val SHORT_CHANNEL_ID_LEN = 8 val FEE_BASE_U32_LEN = 4 val FEE_PROPORTIONAL_LEN = 4 val CLTV_EXPIRTY_DELTA_LEN = 2 val TOTAL_LEN = PUBKEY_LEN + SHORT_CHANNEL_ID_LEN + FEE_BASE_U32_LEN + FEE_PROPORTIONAL_LEN + CLTV_EXPIRTY_DELTA_LEN require( bytes.length >= TOTAL_LEN, s"ByteVector must at least of length $TOTAL_LEN, got ${bytes.length}") val (pubKeyBytes, rest0) = bytes.splitAt(PUBKEY_LEN) val pubKey = ECPublicKey.fromBytes(pubKeyBytes) val (shortChannelIdBytes, rest1) = rest0.splitAt(SHORT_CHANNEL_ID_LEN) val shortChannelId = ShortChannelId.fromBytes(shortChannelIdBytes) val (feeBaseU32Bytes, rest2) = rest1.splitAt(FEE_BASE_U32_LEN) val feeBaseU32 = UInt32.fromBytes(feeBaseU32Bytes) val feeBase = feeBaseU32.toLong val feeBaseMSat = FeeBaseMSat(MilliSatoshis(feeBase)) val (u32Bytes, rest3) = rest2.splitAt(FEE_PROPORTIONAL_LEN) val u32 = UInt32.fromBytes(u32Bytes) val feeProportionalMillionths = FeeProportionalMillionths(u32) val (cltvExpiryDeltaBytes, _) = rest3.splitAt(CLTV_EXPIRTY_DELTA_LEN) val cltvExpiryDelta = new BigInteger( cltvExpiryDeltaBytes.toArray).shortValueExact LnRoute(pubKey, shortChannelId, feeBaseMSat, feeProportionalMillionths, cltvExpiryDelta) } }
Example 121
Source File: LnInvoiceSignature.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.ln import java.math.BigInteger import org.bitcoins.core.number.{UInt5, UInt8} import org.bitcoins.core.util.Bech32 import org.bitcoins.crypto.{ECDigitalSignature, Factory, NetworkElement} import scodec.bits.ByteVector sealed abstract class LnInvoiceSignature extends NetworkElement { require(recoverId.toInt >= 0 && recoverId.toInt <= 3, s"signature recovery byte must be 0,1,2,3, got ${recoverId.toInt}") require( bytes.length == 65, s"LnInvoiceSignatures MUST be 65 bytes in length, got ${bytes.length}") def signature: ECDigitalSignature def recoverId: UInt8 def data: Vector[UInt5] = { val bytes = signature.toRawRS ++ recoverId.bytes Bech32.from8bitTo5bit(bytes) } override def bytes: ByteVector = { signature.toRawRS ++ recoverId.bytes } } object LnInvoiceSignature extends Factory[LnInvoiceSignature] { private case class LnInvoiceSignatureImpl( recoverId: UInt8, signature: ECDigitalSignature) extends LnInvoiceSignature def apply( recoverId: UInt8, signature: ECDigitalSignature): LnInvoiceSignature = { LnInvoiceSignatureImpl(recoverId, signature) } def fromBytes(bytes: ByteVector): LnInvoiceSignature = { val sigBytes = bytes.take(64) val recoverId = UInt8(bytes(64)) val signature = ECDigitalSignature.fromRS(sigBytes) LnInvoiceSignature.apply(recoverId = recoverId, signature = signature) } def fromRS( r: BigInteger, s: BigInteger, recovId: UInt8): LnInvoiceSignature = { val sig = ECDigitalSignature.fromRS(r, s) LnInvoiceSignature(recovId, sig) } def fromU5s(u5s: Vector[UInt5]): LnInvoiceSignature = { val u8s = Bech32.from5bitTo8bit(u5s) val bytes = UInt8.toBytes(u8s) fromBytes(bytes) } }
Example 122
Source File: TransactionOutput.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.transaction import org.bitcoins.core.currency.{CurrencyUnit, CurrencyUnits} import org.bitcoins.core.protocol.script.ScriptPubKey import org.bitcoins.core.serializers.transaction.RawTransactionOutputParser import org.bitcoins.crypto.{Factory, NetworkElement} import scodec.bits.ByteVector case class TransactionOutput(value: CurrencyUnit, scriptPubKey: ScriptPubKey) extends NetworkElement { //https://bitcoin.org/en/developer-reference#txout override lazy val byteSize = scriptPubKey.byteSize + 8 override def bytes = RawTransactionOutputParser.write(this) } final object EmptyTransactionOutput extends TransactionOutput(CurrencyUnits.negativeSatoshi, ScriptPubKey.empty) { override def toString(): String = "EmptyTransactionOutput" } object TransactionOutput extends Factory[TransactionOutput] { def fromBytes(bytes: ByteVector): TransactionOutput = RawTransactionOutputParser.read(bytes) }
Example 123
Source File: OutputReference.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.transaction import org.bitcoins.crypto.{Factory, NetworkElement} import scodec.bits.ByteVector case class OutputReference( outPoint: TransactionOutPoint, output: TransactionOutput) extends NetworkElement { override def bytes: ByteVector = { outPoint.bytes ++ output.bytes } } object EmptyOutputReference extends OutputReference(EmptyTransactionOutPoint, EmptyTransactionOutput) { override def toString: String = "EmptyOutputReference" } object OutputReference extends Factory[OutputReference] { override def fromBytes(bytes: ByteVector): OutputReference = { val (outPointBytes, outputBytes) = bytes.splitAt(36) val outPoint = TransactionOutPoint(outPointBytes) val output = TransactionOutput(outputBytes) OutputReference(outPoint, output) } }
Example 124
Source File: Block.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.protocol.blockchain import org.bitcoins.core.number.UInt64 import org.bitcoins.core.protocol.transaction.Transaction import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.blockchain.RawBlockSerializer import org.bitcoins.crypto.{Factory, NetworkElement} import scodec.bits.ByteVector object Block extends Factory[Block] { sealed private case class BlockImpl( blockHeader: BlockHeader, txCount: CompactSizeUInt, transactions: Seq[Transaction]) extends Block def apply( blockHeader: BlockHeader, txCount: CompactSizeUInt, transactions: Seq[Transaction]): Block = { BlockImpl(blockHeader, txCount, transactions) } def apply(blockHeader: BlockHeader, transactions: Seq[Transaction]): Block = { val txCount = CompactSizeUInt(UInt64(transactions.size)) Block(blockHeader, txCount, transactions) } def fromBytes(bytes: ByteVector): Block = RawBlockSerializer.read(bytes) }
Example 125
Source File: BlockFilter.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.gcs import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.protocol.blockchain.Block import org.bitcoins.core.protocol.script.{EmptyScriptPubKey, ScriptPubKey} import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutput} import org.bitcoins.core.script.control.OP_RETURN import org.bitcoins.core.util.BytesUtil import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector object BlockFilter { def apply( block: Block, prevOutputScripts: Vector[ScriptPubKey]): GolombFilter = { val keyBytes: ByteVector = block.blockHeader.hash.bytes.take(16) val key: SipHashKey = SipHashKey(keyBytes) val newScriptPubKeys: Vector[ByteVector] = getOutputScriptPubKeysFromBlock(block).map(_.asmBytes) val prevOutputScriptBytes: Vector[ByteVector] = prevOutputScripts .filterNot(_ == EmptyScriptPubKey) .map(_.asmBytes) val allOutputs = (prevOutputScriptBytes ++ newScriptPubKeys).distinct GCS.buildBasicBlockFilter(allOutputs, key) } def fromBytes( bytes: ByteVector, blockHash: DoubleSha256Digest): GolombFilter = { val n = CompactSizeUInt.fromBytes(bytes) val filterBytes = bytes.drop(n.bytes.length) val keyBytes: ByteVector = blockHash.bytes.take(16) val key: SipHashKey = SipHashKey(keyBytes) GolombFilter(key, FilterType.Basic.M, FilterType.Basic.P, n, filterBytes.toBitVector) } def fromHex(hex: String, blockHash: DoubleSha256Digest): GolombFilter = { fromBytes(BytesUtil.decodeHex(hex), blockHash) } }
Example 126
Source File: GolombFilter.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.gcs import org.bitcoins.core.number.{UInt64, UInt8} import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.crypto.{ CryptoUtil, DoubleSha256Digest, DoubleSha256DigestBE, NetworkElement } import scodec.bits.{BitVector, ByteVector} def getHeader(prevHeaderHash: DoubleSha256Digest): FilterHeader = { FilterHeader(filterHash = this.hash, prevHeaderHash = prevHeaderHash) } override def bytes: ByteVector = { n.bytes ++ encodedData.bytes } def hashToRange(item: ByteVector): UInt64 = GCS.hashToRange(item, f, key) }
Example 127
Source File: BloomFlag.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.bloom import org.bitcoins.crypto.Factory import scodec.bits.ByteVector case object BloomUpdateP2PKOnly extends BloomFlag { def byte = 2.toByte } object BloomFlag extends Factory[BloomFlag] { private def flags = Seq(BloomUpdateNone, BloomUpdateAll, BloomUpdateP2PKOnly) def apply(byte: Byte): BloomFlag = { val flagOpt = flags.find(_.byte == byte) if (flagOpt.isDefined) flagOpt.get else throw new IllegalArgumentException( "The given byte was not defined for BloomFlag, got: " + byte) } def fromBytes(bytes: ByteVector): BloomFlag = BloomFlag(bytes.head) }
Example 128
Source File: NetworkHeader.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.p2p import org.bitcoins.core.config.NetworkParameters import org.bitcoins.core.number.UInt32 import org.bitcoins.core.serializers.p2p.headers.RawNetworkHeaderSerializer import org.bitcoins.crypto.{CryptoUtil, Factory, NetworkElement} import scodec.bits.ByteVector def apply( network: NetworkParameters, payload: NetworkPayload): NetworkHeader = { val checksum = CryptoUtil.doubleSHA256(payload.bytes) NetworkHeader(network, payload.commandName, UInt32(payload.bytes.size), checksum.bytes.take(4)) } }
Example 129
Source File: TypeIdentifier.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.p2p import org.bitcoins.core.number.UInt32 import org.bitcoins.core.serializers.p2p.messages.RawTypeIdentifierSerializer import org.bitcoins.crypto.{Factory, NetworkElement} import scodec.bits.ByteVector private val MsgWitnessFlag = UInt32(1 << 30) private case class MsgUnassignedImpl(num: UInt32) extends MsgUnassigned override def fromBytes(bytes: ByteVector): TypeIdentifier = RawTypeIdentifierSerializer.read(bytes) def apply(num: Long): TypeIdentifier = TypeIdentifier(UInt32(num)) def apply(uInt32: UInt32): TypeIdentifier = uInt32 match { case UInt32.one => MsgTx case _ if uInt32 == UInt32(2) => MsgBlock case _ if uInt32 == UInt32(3) => MsgFilteredBlock case x: UInt32 => MsgUnassignedImpl(x) } }
Example 130
Source File: BytesUtil.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.util import org.bitcoins.core.number.UInt64 import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.crypto.{CryptoBytesUtil, Factory, NetworkElement} import scodec.bits.ByteVector import scala.annotation.tailrec trait BytesUtil extends CryptoBytesUtil { def writeCmpctSizeUInt[T <: NetworkElement](ts: Seq[T]): ByteVector = { val serialized = ts.map(_.bytes).foldLeft(ByteVector.empty)(_ ++ _) val cmpct = CompactSizeUInt(UInt64(ts.size)) cmpct.bytes ++ serialized } def parseCmpctSizeUIntSeq[T <: NetworkElement]( bytes: ByteVector, factory: Factory[T]): (Vector[T], ByteVector) = { val count = CompactSizeUInt.parse(bytes) val payload = bytes.drop(count.byteSize.toInt) val builder = Vector.newBuilder[T] @tailrec def loop(remaining: ByteVector, counter: Int = 0): ByteVector = { if (counter == count.num.toInt) { remaining } else { val parsed = factory.fromBytes(remaining) val newRemaining = remaining.drop(parsed.byteSize) builder.+=(parsed) loop(newRemaining, counter + 1) } } val remaining = loop(payload) val result = builder.result() require( result.size == count.num.toInt, s"Could not parse the amount of required elements, got: ${result.size} required: ${count}") (result, remaining) } } object BytesUtil extends BytesUtil
Example 131
Source File: RawScriptSignatureParser.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.script import org.bitcoins.core.protocol.script._ import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.util.BitcoinScriptUtil import scodec.bits.ByteVector sealed abstract class RawScriptSignatureParser extends RawBitcoinSerializer[ScriptSignature] { def read(bytes: ByteVector): ScriptSignature = { if (bytes.isEmpty) EmptyScriptSignature else { BitcoinScriptUtil.parseScript(bytes = bytes, f = ScriptSignature.fromAsm) } } def write(scriptSig: ScriptSignature): ByteVector = scriptSig.bytes } object RawScriptSignatureParser extends RawScriptSignatureParser
Example 132
Source File: RawScriptWitnessParser.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.script import org.bitcoins.core.number.UInt64 import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.protocol.script.ScriptWitness import org.bitcoins.core.serializers.RawBitcoinSerializer import scodec.bits.ByteVector import scala.annotation.tailrec sealed abstract class RawScriptWitnessParser extends RawBitcoinSerializer[ScriptWitness] { def read(bytes: ByteVector): ScriptWitness = { //first byte is the number of stack items val stackSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val (_, stackBytes) = bytes.splitAt(stackSize.byteSize.toInt) @tailrec def loop( remainingBytes: ByteVector, accum: Seq[ByteVector], remainingStackItems: UInt64): Seq[ByteVector] = { if (remainingStackItems <= UInt64.zero) accum else { val elementSize = CompactSizeUInt.parseCompactSizeUInt(remainingBytes) val (_, stackElementBytes) = remainingBytes.splitAt(elementSize.byteSize.toInt) val stackElement = stackElementBytes.take(elementSize.num.toInt) val (_, newRemainingBytes) = stackElementBytes.splitAt(stackElement.size) loop(newRemainingBytes, stackElement +: accum, remainingStackItems - UInt64.one) } } //note there is no 'reversing' the accum, in bitcoin-s we assume the top of the stack is the 'head' element in the sequence val stack = loop(stackBytes, Nil, stackSize.num) val witness = ScriptWitness(stack) witness } def write(scriptWitness: ScriptWitness): ByteVector = { @tailrec def loop( remainingStack: Seq[ByteVector], accum: Vector[ByteVector]): Vector[ByteVector] = { if (remainingStack.isEmpty) accum.reverse else { val compactSizeUInt: CompactSizeUInt = CompactSizeUInt.calc(remainingStack.head) val serialization: ByteVector = compactSizeUInt.bytes ++ remainingStack.head loop(remainingStack.tail, serialization +: accum) } } val stackItems: Vector[ByteVector] = loop(scriptWitness.stack.reverse, Vector.empty) val size = CompactSizeUInt(UInt64(stackItems.size)) (size.bytes +: stackItems).fold(ByteVector.empty)(_ ++ _) } } object RawScriptWitnessParser extends RawScriptWitnessParser
Example 133
Source File: RawScriptPubKeyParser.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.script import org.bitcoins.core.protocol.script.{EmptyScriptPubKey, ScriptPubKey} import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.util.BitcoinScriptUtil import scodec.bits.ByteVector trait RawScriptPubKeyParser extends RawBitcoinSerializer[ScriptPubKey] { override def read(bytes: ByteVector): ScriptPubKey = { if (bytes.isEmpty) EmptyScriptPubKey else { BitcoinScriptUtil.parseScript(bytes = bytes, f = ScriptPubKey.fromAsm) } } override def write(scriptPubKey: ScriptPubKey): ByteVector = scriptPubKey.bytes } object RawScriptPubKeyParser extends RawScriptPubKeyParser
Example 134
Source File: RawTransactionOutputParser.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.transaction import org.bitcoins.core.currency.{CurrencyUnits, Satoshis} import org.bitcoins.core.protocol.transaction.TransactionOutput import org.bitcoins.core.serializers.script.RawScriptPubKeyParser import org.bitcoins.core.serializers.{ RawBitcoinSerializer, RawSatoshisSerializer } import scodec.bits.ByteVector override def read(bytes: ByteVector): TransactionOutput = { val satoshisBytes = bytes.take(8) val satoshis = RawSatoshisSerializer.read(satoshisBytes) //it doesn't include itself towards the size, thats why it is incremented by one val scriptPubKeyBytes = bytes.slice(8, bytes.size) val scriptPubKey = RawScriptPubKeyParser.read(scriptPubKeyBytes) val parsedOutput = TransactionOutput(satoshis, scriptPubKey) parsedOutput } } object RawTransactionOutputParser extends RawTransactionOutputParser
Example 135
Source File: RawTransactionOutPointParser.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.transaction import org.bitcoins.core.number.UInt32 import org.bitcoins.core.protocol.transaction.{ EmptyTransactionOutPoint, TransactionOutPoint } import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector sealed abstract class RawTransactionOutPointParser extends RawBitcoinSerializer[TransactionOutPoint] { override def read(bytes: ByteVector): TransactionOutPoint = { val txId: ByteVector = bytes.take(32) val indexBytes = bytes.slice(32, 36) val index = UInt32(indexBytes.reverse) TransactionOutPoint(DoubleSha256Digest(txId), index) } def write(outPoint: TransactionOutPoint): ByteVector = { //UInt32s cannot hold negative numbers, but sometimes the Bitcoin Protocol requires the vout to be -1, which is serialized //as "0xFFFFFFFF". //https://github.com/bitcoin/bitcoin/blob/d612837814020ae832499d18e6ee5eb919a87907/src/primitives/transaction.h //http://stackoverflow.com/questions/2711522/what-happens-if-i-assign-a-negative-value-to-an-unsigned-variable val idxBytes = outPoint match { case EmptyTransactionOutPoint => UInt32.max.bytes case outPoint: TransactionOutPoint => outPoint.vout.bytes } val txIdHex = outPoint.txId.bytes txIdHex ++ idxBytes.reverse } } object RawTransactionOutPointParser extends RawTransactionOutPointParser
Example 136
Source File: RawTransactionWitnessParser.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.transaction import org.bitcoins.core.protocol.script.ScriptWitness import org.bitcoins.core.protocol.transaction.TransactionWitness import org.bitcoins.core.serializers.script.RawScriptWitnessParser import scodec.bits.ByteVector import scala.annotation.tailrec def read(bytes: ByteVector, numInputs: Int): TransactionWitness = { @tailrec def loop( remainingBytes: ByteVector, remainingInputs: Int, accum: Vector[ScriptWitness]): Vector[ScriptWitness] = { if (remainingInputs != 0) { val w = RawScriptWitnessParser.read(remainingBytes) val (_, newRemainingBytes) = remainingBytes.splitAt(w.bytes.size) loop(newRemainingBytes, remainingInputs - 1, w +: accum) } else accum.reverse } val witnesses = loop(bytes, numInputs, Vector.empty) require(witnesses.size == numInputs) TransactionWitness(witnesses) } def write(witness: TransactionWitness): ByteVector = { witness.foldLeft(ByteVector.empty)(_ ++ _.bytes) } } object RawTransactionWitnessParser extends RawTransactionWitnessParser
Example 137
Source File: RawBitcoinSerializerHelper.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers import org.bitcoins.core.number.UInt64 import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.crypto.NetworkElement import scodec.bits.ByteVector import scala.annotation.tailrec final def writeNetworkElements[T <: NetworkElement]( ts: Seq[T]): ByteVector = { val f = { t: T => t.bytes } write(ts, f) } final def write[T](ts: Seq[T], serializer: T => ByteVector): ByteVector = { ts.foldLeft(ByteVector.empty) { case (accum, t) => accum ++ serializer(t) } } } object RawSerializerHelper extends RawSerializerHelper
Example 138
Source File: RawBloomFilterSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.bloom import org.bitcoins.core.bloom.{BloomFilter, BloomFlag} import org.bitcoins.core.number.UInt32 import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.RawBitcoinSerializer import scodec.bits.ByteVector sealed abstract class RawBloomFilterSerializer extends RawBitcoinSerializer[BloomFilter] { override def read(bytes: ByteVector): BloomFilter = { val filterSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val filter = bytes.slice(filterSize.byteSize.toInt, filterSize.byteSize.toInt + filterSize.num.toInt) val hashFuncsIndex = (filterSize.byteSize + filterSize.num.toInt).toInt val hashFuncs = UInt32( bytes.slice(hashFuncsIndex, hashFuncsIndex + 4).reverse) val tweakIndex = hashFuncsIndex + 4 val tweak = UInt32(bytes.slice(tweakIndex, tweakIndex + 4).reverse) val flags = BloomFlag(bytes(tweakIndex + 4)) BloomFilter(filterSize, filter, hashFuncs, tweak, flags) } override def write(bloomFilter: BloomFilter): ByteVector = { bloomFilter.filterSize.bytes ++ bloomFilter.data ++ bloomFilter.hashFuncs.bytes.reverse ++ bloomFilter.tweak.bytes.reverse ++ ByteVector.fromByte(bloomFilter.flags.byte) } } object RawBloomFilterSerializer extends RawBloomFilterSerializer
Example 139
Source File: RawNetworkMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p import org.bitcoins.core.p2p._ import org.bitcoins.core.serializers.RawBitcoinSerializer import scodec.bits.ByteVector trait RawNetworkMessageSerializer extends RawBitcoinSerializer[NetworkMessage] { def read(bytes: ByteVector): NetworkMessage = { //first 24 bytes are the header val (headerBytes, payloadBytes) = bytes.splitAt(24) val header = NetworkHeader.fromBytes(headerBytes) if (header.payloadSize.toInt > payloadBytes.length) { throw new RuntimeException( s"We do not have enough bytes for payload! Expected=${header.payloadSize.toInt} got=${payloadBytes.length}") } else { val payload = NetworkPayload(header, payloadBytes) val n = NetworkMessage(header, payload) n } } def write(networkMessage: NetworkMessage): ByteVector = { networkMessage.header.bytes ++ networkMessage.payload.bytes } } object RawNetworkMessageSerializer extends RawNetworkMessageSerializer
Example 140
Source File: RawGetCompactFiltersMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.gcs.FilterType import org.bitcoins.core.number.UInt32 import org.bitcoins.core.p2p.GetCompactFiltersMessage import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector object RawGetCompactFiltersMessageSerializer extends RawBitcoinSerializer[GetCompactFiltersMessage] { def read(bytes: ByteVector): GetCompactFiltersMessage = { val filterType = FilterType.fromBytes(bytes.take(1)) val (startHeightBytes, rest) = bytes.drop(1).splitAt(4) val startHeight = UInt32.fromBytes(startHeightBytes.reverse) val stopHash = DoubleSha256Digest.fromBytes(rest.take(32)) GetCompactFiltersMessage(filterType, startHeight, stopHash) } def write(message: GetCompactFiltersMessage): ByteVector = { val filterType = message.filterType.bytes val startHeight = message.startHeight.bytes.reverse val stopHash = message.stopHash.bytes val bytes = filterType ++ startHeight ++ stopHash bytes } }
Example 141
Source File: RawFilterLoadMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.serializers.bloom.RawBloomFilterSerializer import org.bitcoins.core.p2p.FilterLoadMessage import scodec.bits.ByteVector trait RawFilterLoadMessageSerializer extends RawBitcoinSerializer[FilterLoadMessage] { override def read(bytes: ByteVector): FilterLoadMessage = { val filter = RawBloomFilterSerializer.read(bytes) FilterLoadMessage(filter) } override def write(filterLoadMessage: FilterLoadMessage): ByteVector = { RawBloomFilterSerializer.write(filterLoadMessage.bloomFilter) } } object RawFilterLoadMessageSerializer extends RawFilterLoadMessageSerializer
Example 142
Source File: RawGetBlocksMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper} import org.bitcoins.core.p2p._ import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector import scala.annotation.tailrec private def parseBlockHeaders( bytes: ByteVector, compactSizeUInt: CompactSizeUInt): ( List[DoubleSha256Digest], ByteVector) = { @tailrec def loop( remainingHeaders: Long, accum: List[DoubleSha256Digest], remainingBytes: ByteVector): (List[DoubleSha256Digest], ByteVector) = { if (remainingHeaders <= 0) (accum.reverse, remainingBytes) else { val dsha256 = DoubleSha256Digest(remainingBytes.slice(0, 32)) val rem = remainingBytes.slice(32, remainingBytes.size) loop(remainingHeaders = remainingHeaders - 1, accum = dsha256 :: accum, remainingBytes = rem) } } loop(compactSizeUInt.num.toInt, List.empty, bytes) } } object RawGetBlocksMessageSerializer extends RawGetBlocksMessageSerializer
Example 143
Source File: RawCompactFilterCheckpointMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.gcs.FilterType import org.bitcoins.core.p2p.CompactFilterCheckPointMessage import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper} import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector object RawCompactFilterCheckpointMessageSerializer extends RawBitcoinSerializer[CompactFilterCheckPointMessage] { def read(bytes: ByteVector): CompactFilterCheckPointMessage = { val filterType = FilterType.fromBytes(bytes.take(1)) val (stopHashBytes, afterStopHash) = bytes.drop(1).splitAt(32) val stopHash = DoubleSha256Digest.fromBytes(stopHashBytes) val filterHeadersLength = CompactSizeUInt.parse(afterStopHash) val (headers, _) = RawSerializerHelper.parseCmpctSizeUIntSeq( afterStopHash, { bytes => DoubleSha256Digest.fromBytes(bytes.take(32)) }) require( headers.length == filterHeadersLength.toInt, s"Invalid compact filter checkpoint message: expected number of headers ${filterHeadersLength.toInt}, but got ${headers.length}" ) CompactFilterCheckPointMessage(filterType, stopHash, headers.toVector) } def write(message: CompactFilterCheckPointMessage): ByteVector = { val filterType = message.filterType.bytes val stopHash = message.stopHash.bytes val filterHeaders = RawSerializerHelper.writeCmpctSizeUInt(message.filterHeaders, { fh: DoubleSha256Digest => fh.bytes }) filterType ++ stopHash ++ filterHeaders } }
Example 144
Source File: RawGetDataMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.p2p.{GetDataMessage, InventoryMessage} import scodec.bits.ByteVector trait RawGetDataMessageSerializer extends RawBitcoinSerializer[GetDataMessage] { //InventoryMessages & GetDataMessages have the same structure and are serialized the same //so we can piggy back off of the serialilzers for InventoryMessages def read(bytes: ByteVector): GetDataMessage = { val inv = InventoryMessage(bytes) GetDataMessage(inv.inventoryCount, inv.inventories) } def write(getDataMessage: GetDataMessage): ByteVector = { val inv = InventoryMessage(getDataMessage.inventoryCount, getDataMessage.inventories) inv.bytes } } object RawGetDataMessageSerializer extends RawGetDataMessageSerializer
Example 145
Source File: RawNotFoundMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.p2p.{InventoryMessage, NotFoundMessage} import scodec.bits.ByteVector trait RawNotFoundMessageSerializer extends RawBitcoinSerializer[NotFoundMessage] { override def read(bytes: ByteVector): NotFoundMessage = { //this seems funky, but according to the documentation inventory messages //and NotFoundMessages have the same structure, therefore we can piggy back //off of the serializer used by InventoryMessage val inventoryMessage = InventoryMessage(bytes) NotFoundMessage(inventoryMessage.inventoryCount, inventoryMessage.inventories) } override def write(notFoundMessage: NotFoundMessage): ByteVector = { //Since InventoryMessages and NotFoundMessages have the same format //we can just create an inventory message then piggy back off of the //serializer used by inventory message val inventoryMessage = InventoryMessage(notFoundMessage.inventoryCount, notFoundMessage.inventories) inventoryMessage.bytes } } object RawNotFoundMessageSerializer extends RawNotFoundMessageSerializer
Example 146
Source File: RawCompactFilterMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.gcs.FilterType import org.bitcoins.core.number.UInt64 import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.p2p.CompactFilterMessage import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector object RawCompactFilterMessageSerializer extends RawBitcoinSerializer[CompactFilterMessage] { def read(bytes: ByteVector): CompactFilterMessage = { val filterType = FilterType.fromBytes(bytes.take(1)) val (blockHashBytes, afterBlockHash) = bytes.drop(1).splitAt(32) val blockHash = DoubleSha256Digest.fromBytes(blockHashBytes) val mumFilterBytes = CompactSizeUInt.parse(afterBlockHash) val filterBytes = afterBlockHash .drop(mumFilterBytes.bytes.length) .take(mumFilterBytes.toInt) CompactFilterMessage(filterType, blockHash, filterBytes) } def write(message: CompactFilterMessage): ByteVector = { val filterType = message.filterType.bytes val blockHash = message.blockHash.bytes val numFilterBytes = CompactSizeUInt(UInt64(message.filterBytes.size)).bytes val filterBytes = message.filterBytes filterType ++ blockHash ++ numFilterBytes ++ filterBytes } }
Example 147
Source File: RawGetCompactFilterHeadersMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.gcs.FilterType import org.bitcoins.core.number.UInt32 import org.bitcoins.core.p2p.GetCompactFilterHeadersMessage import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector object RawGetCompactFilterHeadersMessageSerializer extends RawBitcoinSerializer[GetCompactFilterHeadersMessage] { def read(bytes: ByteVector): GetCompactFilterHeadersMessage = { val filterType = FilterType.fromBytes(bytes.take(1)) val startHeight = UInt32.fromBytes(bytes.drop(1).take(4).reverse) val stopHash = bytes.drop(5).take(32) GetCompactFilterHeadersMessage( filterType = filterType, startHeight = startHeight, stopHash = DoubleSha256Digest.fromBytes(stopHash) ) } def write(message: GetCompactFilterHeadersMessage): ByteVector = { val filterType = message.filterType.bytes val startHeight = message.startHeight.bytes.reverse val stopHash = message.stopHash.bytes val bytes = filterType ++ startHeight ++ stopHash bytes } }
Example 148
Source File: RawGetHeadersMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper} import org.bitcoins.core.p2p._ import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector import scala.annotation.tailrec trait RawGetHeadersMessageSerializer extends RawBitcoinSerializer[GetHeadersMessage] { override def read(bytes: ByteVector): GetHeadersMessage = { val version = ProtocolVersion(bytes.take(4)) val hashCount = CompactSizeUInt.parseCompactSizeUInt(bytes.slice(4, bytes.length)) val hashesStartIndex = (hashCount.byteSize + 4).toInt val (hashes, remainingBytes) = parseHashes(bytes.slice(hashesStartIndex, bytes.length), hashCount) val hashStop = DoubleSha256Digest(remainingBytes.take(32)) GetHeadersMessage(version, hashCount, hashes, hashStop) } override def write(getHeadersMessage: GetHeadersMessage): ByteVector = { getHeadersMessage.version.bytes ++ getHeadersMessage.hashCount.bytes ++ RawSerializerHelper.writeNetworkElements(getHeadersMessage.hashes) ++ getHeadersMessage.hashStop.bytes } private def parseHashes( bytes: ByteVector, numHashes: CompactSizeUInt): (List[DoubleSha256Digest], ByteVector) = { @tailrec def loop( remainingBytes: ByteVector, remainingHashes: Long, accum: List[DoubleSha256Digest]): ( List[DoubleSha256Digest], ByteVector) = { if (remainingHashes <= 0) (accum.reverse, remainingBytes) else { val hash = DoubleSha256Digest(remainingBytes.take(32)) loop(remainingBytes.slice(32, remainingBytes.length), remainingHashes - 1, hash :: accum) } } loop(bytes, numHashes.num.toInt, List.empty) } } object RawGetHeadersMessageSerializer extends RawGetHeadersMessageSerializer
Example 149
Source File: RawCompactFilterHeadersMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.gcs.FilterType import org.bitcoins.core.p2p.CompactFilterHeadersMessage import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper} import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector object RawCompactFilterHeadersMessageSerializer extends RawBitcoinSerializer[CompactFilterHeadersMessage] { def read(bytes: ByteVector): CompactFilterHeadersMessage = { val filterType = FilterType.fromBytes(bytes.take(1)) val (stopHashBytes, afterStopHash) = bytes.drop(1).splitAt(32) val stopHash = DoubleSha256Digest.fromBytes(stopHashBytes) val (previousFilterHeaderBytes, afterPreviousFilterHeader) = afterStopHash.splitAt(32) val previousFilterHeaderHash = DoubleSha256Digest.fromBytes(previousFilterHeaderBytes) val (hashes, _) = RawSerializerHelper.parseCmpctSizeUIntSeq( afterPreviousFilterHeader, { bytes => DoubleSha256Digest.fromBytes(bytes.take(32)) }) val message = CompactFilterHeadersMessage(filterType, stopHash, previousFilterHeaderHash, hashes.toVector) message } def write(message: CompactFilterHeadersMessage): ByteVector = { val filterType = message.filterType.bytes val stopHash = message.stopHash.bytes val previousFilterHeader = message.previousFilterHeader.bytes val filterHashes = RawSerializerHelper.writeCmpctSizeUInt(message.filterHashes, { fh: DoubleSha256Digest => fh.bytes }) filterType ++ stopHash ++ previousFilterHeader ++ filterHashes } }
Example 150
Source File: RawVersionMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import java.net.InetAddress import org.bitcoins.core.number.{Int32, Int64, UInt32, UInt64} import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.util.BitcoinSLogger import org.bitcoins.core.p2p._ import scodec.bits.ByteVector trait RawVersionMessageSerializer extends RawBitcoinSerializer[VersionMessage] with BitcoinSLogger { def read(bytes: ByteVector): VersionMessage = { val version = ProtocolVersion(bytes.take(4)) val services = ServiceIdentifier(bytes.slice(4, 12)) val timestamp = Int64(bytes.slice(12, 20).reverse) val addressReceiveServices = ServiceIdentifier(bytes.slice(20, 28)) val addressReceiveIpAddress = InetAddress.getByAddress(bytes.slice(28, 44).toArray) val addressReceivePort = UInt32(bytes.slice(44, 46)).toInt val addressTransServices = ServiceIdentifier(bytes.slice(46, 54)) val addressTransIpAddress = InetAddress.getByAddress(bytes.slice(54, 70).toArray) val addressTransPort = UInt32(bytes.slice(70, 72)).toInt val nonce = UInt64(bytes.slice(72, 80)) val userAgentSize = CompactSizeUInt.parseCompactSizeUInt(bytes.slice(80, bytes.size)) val userAgentBytesStartIndex = 80 + userAgentSize.byteSize.toInt val userAgentBytes = bytes.slice( userAgentBytesStartIndex, userAgentBytesStartIndex + userAgentSize.num.toInt) val userAgent = userAgentBytes.toArray.map(_.toChar).mkString val startHeightStartIndex = userAgentBytesStartIndex + userAgentSize.num.toInt val startHeight = Int32( bytes.slice(startHeightStartIndex, startHeightStartIndex + 4).reverse) val relay = bytes(startHeightStartIndex + 4) != 0 VersionMessage( version = version, services = services, timestamp = timestamp, addressReceiveServices = addressReceiveServices, addressReceiveIpAddress = addressReceiveIpAddress, addressReceivePort = addressReceivePort, addressTransServices = addressTransServices, addressTransIpAddress = addressTransIpAddress, addressTransPort = addressTransPort, nonce = nonce, userAgent = userAgent, startHeight = startHeight, relay = relay ) } def write(versionMessage: VersionMessage): ByteVector = { versionMessage.version.bytes ++ versionMessage.services.bytes ++ versionMessage.timestamp.bytes.reverse ++ versionMessage.addressReceiveServices.bytes ++ NetworkIpAddress.writeAddress(versionMessage.addressReceiveIpAddress) ++ //encode hex returns 8 characters, but we only need the last 4 since port number is a uint16 //check for precision loss here? ByteVector.fromShort(versionMessage.addressReceivePort.toShort) ++ versionMessage.addressTransServices.bytes ++ NetworkIpAddress.writeAddress(versionMessage.addressTransIpAddress) ++ //encode hex returns 8 characters, but we only need the last 4 since port number is a uint16 //check for precision loss here? ByteVector.fromShort(versionMessage.addressTransPort.toShort) ++ versionMessage.nonce.bytes ++ versionMessage.userAgentSize.bytes ++ ByteVector(versionMessage.userAgent.getBytes) ++ versionMessage.startHeight.bytes.reverse ++ (if (versionMessage.relay) ByteVector.fromByte(1.toByte) else ByteVector.fromByte(0.toByte)) } } object RawVersionMessageSerializer extends RawVersionMessageSerializer
Example 151
Source File: RawHeadersMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.protocol.blockchain.BlockHeader import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.p2p.HeadersMessage import scodec.bits.ByteVector import scala.annotation.tailrec trait RawHeadersMessageSerializer extends RawBitcoinSerializer[HeadersMessage] { def read(bytes: ByteVector): HeadersMessage = { val compactSizeUInt = CompactSizeUInt.parseCompactSizeUInt(bytes) val headerStartIndex = compactSizeUInt.byteSize.toInt val headerBytes = bytes.slice(headerStartIndex, bytes.length) val headers = parseBlockHeaders(headerBytes, compactSizeUInt) HeadersMessage(compactSizeUInt, headers) } def write(headersMessage: HeadersMessage): ByteVector = { val z = ByteVector.fromByte(0.toByte) val headerBytes = headersMessage.headers.foldLeft(ByteVector.empty) { case (accum, msg) => accum ++ msg.bytes ++ z } headersMessage.count.bytes ++ headerBytes } private def parseBlockHeaders( bytes: ByteVector, compactSizeUInt: CompactSizeUInt): Vector[BlockHeader] = { @tailrec def loop( remainingBytes: ByteVector, remainingHeaders: Long, accum: List[BlockHeader]): List[BlockHeader] = { if (remainingHeaders <= 0) accum //81 is because HeadersMessage appends 0x00 at the end of every block header for some reason //read https://bitcoin.org/en/developer-reference#headers else { require( remainingBytes.size >= 80, "We do not have enough bytes for another block header, this probably means a tcp frame was not aligned") loop(remainingBytes = remainingBytes.slice(81, remainingBytes.length), remainingHeaders = remainingHeaders - 1, accum = BlockHeader(remainingBytes.take(80)) :: accum) } } loop(bytes, compactSizeUInt.num.toInt, List.empty).reverse.toVector } } object RawHeadersMessageSerializer extends RawHeadersMessageSerializer
Example 152
Source File: RawFeeFilterMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.currency.Satoshis import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.wallet.fee.SatoshisPerKiloByte import org.bitcoins.core.p2p._ import scodec.bits.ByteVector sealed abstract class RawFeeFilterMessageSerializer extends RawBitcoinSerializer[FeeFilterMessage] { override def read(bytes: ByteVector): FeeFilterMessage = { val satBytes = bytes.take(8).reverse val sat = Satoshis(satBytes) val satPerKb = SatoshisPerKiloByte(sat) FeeFilterMessage(satPerKb) } override def write(feeFilterMessage: FeeFilterMessage): ByteVector = { feeFilterMessage.feeRate.currencyUnit.satoshis.bytes.reverse } } object RawFeeFilterMessageSerializer extends RawFeeFilterMessageSerializer
Example 153
Source File: RawRejectMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.p2p.RejectMessage import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.RawBitcoinSerializer import scodec.bits.ByteVector trait RawRejectMessageSerializer extends RawBitcoinSerializer[RejectMessage] { def read(bytes: ByteVector): RejectMessage = { val messageSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val message: String = bytes .slice(messageSize.byteSize.toInt, messageSize.byteSize.toInt + messageSize.num.toInt) .toArray .map(_.toChar) .mkString val code: Char = bytes( messageSize.byteSize.toInt + messageSize.num.toInt).toChar val reasonSizeStartIndex = messageSize.byteSize.toInt + messageSize.num.toInt + 1 val reasonSize = CompactSizeUInt.parseCompactSizeUInt( bytes.slice(reasonSizeStartIndex.toInt, bytes.size)) val reason = bytes .slice( (reasonSizeStartIndex + reasonSize.byteSize).toInt, (reasonSizeStartIndex + reasonSize.byteSize.toInt + reasonSize.num.toInt)) .toArray .map(_.toChar) .mkString val extraStartIndex = reasonSizeStartIndex + reasonSize.byteSize.toInt + reasonSize.num.toInt val extra = bytes.slice(extraStartIndex, bytes.size) RejectMessage(messageSize, message, code, reasonSize, reason, extra) } def write(rejectMessage: RejectMessage): ByteVector = { rejectMessage.messageSize.bytes ++ ByteVector(rejectMessage.message.map(_.toByte)) ++ ByteVector.fromByte(rejectMessage.code.toByte) ++ rejectMessage.reasonSize.bytes ++ ByteVector(rejectMessage.reason.map(_.toByte)) ++ rejectMessage.extra } } object RawRejectMessageSerializer extends RawRejectMessageSerializer
Example 154
Source File: RawFilterAddMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.p2p._ import scodec.bits.ByteVector trait RawFilterAddMessageSerializer extends RawBitcoinSerializer[FilterAddMessage] { override def read(bytes: ByteVector): FilterAddMessage = { val elementSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val element = bytes.slice(elementSize.byteSize.toInt, bytes.size) FilterAddMessage(elementSize, element) } override def write(filterAddMessage: FilterAddMessage): ByteVector = { filterAddMessage.elementSize.bytes ++ filterAddMessage.element } } object RawFilterAddMessageSerializer extends RawFilterAddMessageSerializer
Example 155
Source File: RawGetCompactFilterCheckpointMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.gcs.FilterType import org.bitcoins.core.p2p.GetCompactFilterCheckPointMessage import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector object RawGetCompactFilterCheckpointMessageSerializer extends RawBitcoinSerializer[GetCompactFilterCheckPointMessage] { def read(bytes: ByteVector): GetCompactFilterCheckPointMessage = { val filterType = FilterType.fromBytes(bytes.take(1)) val stopHash = bytes.drop(1).take(32) GetCompactFilterCheckPointMessage( filterType = filterType, stopHash = DoubleSha256Digest.fromBytes(stopHash) ) } def write(message: GetCompactFilterCheckPointMessage): ByteVector = { val filterType = message.filterType.bytes val stopHash = message.stopHash.bytes val bytes = filterType ++ stopHash bytes } }
Example 156
Source File: RawInventoryMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper} import org.bitcoins.core.p2p.{Inventory, InventoryMessage} import scodec.bits.ByteVector import scala.annotation.tailrec private def parseInventories( bytes: ByteVector, requiredInventories: CompactSizeUInt): (List[Inventory], ByteVector) = { @tailrec def loop( remainingInventories: Long, remainingBytes: ByteVector, accum: List[Inventory]): (List[Inventory], ByteVector) = { if (remainingInventories <= 0) (accum.reverse, remainingBytes) else { val inventory = RawInventorySerializer.read(remainingBytes.slice(0, 36)) loop(remainingInventories - 1, remainingBytes.slice(36, remainingBytes.size), inventory :: accum) } } loop(requiredInventories.num.toInt, bytes, List.empty) } } object RawInventoryMessageSerializer extends RawInventoryMessageSerializer
Example 157
Source File: RawAddrMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper} import org.bitcoins.core.serializers.p2p._ import org.bitcoins.core.p2p._ import scodec.bits.ByteVector import scala.annotation.tailrec private def parseNetworkIpAddresses( ipCount: CompactSizeUInt, bytes: ByteVector): (Seq[NetworkIpAddress], ByteVector) = { @tailrec def loop( remainingAddresses: BigInt, remainingBytes: ByteVector, accum: List[NetworkIpAddress]): (Seq[NetworkIpAddress], ByteVector) = { if (remainingAddresses <= 0) (accum.reverse, remainingBytes) else { val networkIpAddress = RawNetworkIpAddressSerializer.read(remainingBytes) val newRemainingBytes = remainingBytes.slice(networkIpAddress.byteSize, remainingBytes.size) loop(remainingAddresses - 1, newRemainingBytes, networkIpAddress :: accum) } } loop(ipCount.num.toInt, bytes, List()) } } object RawAddrMessageSerializer extends RawAddrMessageSerializer
Example 158
Source File: RawTransactionMessageSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.protocol.transaction.Transaction import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.p2p.TransactionMessage import scodec.bits.ByteVector trait RawTransactionMessageSerializer extends RawBitcoinSerializer[TransactionMessage] { def read(bytes: ByteVector): TransactionMessage = { val transaction = Transaction(bytes) TransactionMessage(transaction) } def write(transactionMessage: TransactionMessage): ByteVector = { transactionMessage.transaction.bytes } } object RawTransactionMessageSerializer extends RawTransactionMessageSerializer
Example 159
Source File: RawInventorySerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.messages import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.p2p.TypeIdentifier import org.bitcoins.core.p2p.Inventory import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.ByteVector trait RawInventorySerializer extends RawBitcoinSerializer[Inventory] { override def read(bytes: ByteVector): Inventory = { val typeIdentifier = TypeIdentifier(bytes.take(4)) val hash = DoubleSha256Digest(bytes.slice(4, bytes.size)) Inventory(typeIdentifier, hash) } override def write(inventory: Inventory): ByteVector = { inventory.typeIdentifier.bytes ++ inventory.hash.bytes } } object RawInventorySerializer extends RawInventorySerializer
Example 160
Source File: RawNetworkHeaderSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p.headers import org.bitcoins.core.number.UInt32 import org.bitcoins.core.config._ import org.bitcoins.core.p2p.NetworkHeader import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.util.BitcoinSLogger import scodec.bits.ByteVector def write(messageHeader: NetworkHeader): ByteVector = { val network = messageHeader.network val commandNameNoPadding = messageHeader.commandName.map(_.toByte) //command name needs to be 12 bytes in size, or 24 chars in hex val commandName = ByteVector(commandNameNoPadding).padRight(12) val checksum = messageHeader.checksum network.magicBytes ++ commandName ++ messageHeader.payloadSize.bytes.reverse ++ checksum } } object RawNetworkHeaderSerializer extends RawNetworkHeaderSerializer
Example 161
Source File: RawNetworkIpAddressSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.p2p import java.net.InetAddress import org.bitcoins.core.number.UInt32 import org.bitcoins.core.p2p._ import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.util.BitcoinSLogger import scodec.bits.ByteVector trait RawNetworkIpAddressSerializer extends RawBitcoinSerializer[NetworkIpAddress] with BitcoinSLogger { def read(bytes: ByteVector): NetworkIpAddress = { val time = UInt32(bytes.take(4).reverse) val services = ServiceIdentifier(bytes.slice(4, 12)) val ipBytes = bytes.slice(12, 28) val ipAddress = InetAddress.getByAddress(ipBytes.toArray) val port = bytes.slice(28, 30).toInt(signed = false) NetworkIpAddress(time, services, ipAddress, port) } def write(networkIpAddress: NetworkIpAddress): ByteVector = { val time = networkIpAddress.time.bytes.reverse val services = networkIpAddress.services.bytes val ipAddress = NetworkIpAddress.writeAddress(networkIpAddress.address) // uint16s are only 4 hex characters // cannot do fromShort, val port = ByteVector.fromInt(networkIpAddress.port, size = 2) time ++ services ++ ipAddress ++ port } } object RawNetworkIpAddressSerializer extends RawNetworkIpAddressSerializer
Example 162
Source File: RawMerkleBlockSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.blockchain import org.bitcoins.core.number.{UInt32, UInt64} import org.bitcoins.core.protocol.CompactSizeUInt import org.bitcoins.core.protocol.blockchain.MerkleBlock import org.bitcoins.core.serializers.RawBitcoinSerializer import org.bitcoins.core.util.BytesUtil import org.bitcoins.crypto.DoubleSha256Digest import scodec.bits.{BitVector, ByteVector} import scala.annotation.tailrec private def parseTransactionHashes( bytes: ByteVector, hashCount: CompactSizeUInt): (Seq[DoubleSha256Digest], ByteVector) = { @tailrec def loop( remainingHashes: Long, remainingBytes: ByteVector, accum: List[DoubleSha256Digest]): ( Seq[DoubleSha256Digest], ByteVector) = { if (remainingHashes <= 0) (accum.reverse, remainingBytes) else { val (hashBytes, newRemainingBytes) = remainingBytes.splitAt(32) loop(remainingHashes - 1, newRemainingBytes, DoubleSha256Digest(hashBytes) :: accum) } } loop(hashCount.num.toInt, bytes, Nil) } } object RawMerkleBlockSerializer extends RawMerkleBlockSerializer
Example 163
Source File: RawBlockSerializer.scala From bitcoin-s with MIT License | 5 votes |
package org.bitcoins.core.serializers.blockchain import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader} import org.bitcoins.core.protocol.transaction.Transaction import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper} import scodec.bits.ByteVector def write(block: Block): ByteVector = { val writtenHeader = block.blockHeader.bytes val txBytes = RawSerializerHelper.writeCmpctSizeUInt(block.transactions, { tx: Transaction => tx.bytes }) writtenHeader ++ txBytes } } object RawBlockSerializer extends RawBlockSerializer
Example 164
Source File: TopicConsumer.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.replicator import cats.Monad import cats.data.{NonEmptyList => Nel} import cats.implicits._ import com.evolutiongaming.kafka.journal.{ConsRecord, KafkaConsumer} import com.evolutiongaming.skafka._ import com.evolutiongaming.skafka.consumer._ import com.evolutiongaming.sstream.Stream import scodec.bits.ByteVector import scala.concurrent.duration._ trait TopicConsumer[F[_]] { def subscribe(listener: RebalanceListener[F]): F[Unit] def poll: Stream[F, Map[Partition, Nel[ConsRecord]]] def commit: TopicCommit[F] } object TopicConsumer { def apply[F[_] : Monad]( topic: Topic, pollTimeout: FiniteDuration, commit: TopicCommit[F], consumer: KafkaConsumer[F, String, ByteVector], ): TopicConsumer[F] = { val commit1 = commit new TopicConsumer[F] { def subscribe(listener: RebalanceListener[F]) = { consumer.subscribe(topic, listener.some) } val poll = { val records = for { records <- consumer.poll(pollTimeout) } yield for { (partition, records) <- records.values } yield { (partition.partition, records) } Stream.repeat(records) } def commit = commit1 } } }
Example 165
Source File: Events.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal import cats.data.{NonEmptyList => Nel} import java.lang.{Byte => ByteJ} import com.evolutiongaming.kafka.journal.util.ScodecHelper._ import scodec.bits.ByteVector import scodec.{Codec, codecs} import scala.util.Try final case class Events[A](events: Nel[Event[A]], metadata: PayloadMetadata) object Events { implicit def codecEvents[A](implicit eventCodec: Codec[Event[A]], metadataCodec: Codec[PayloadMetadata] ): Codec[Events[A]] = { val eventsCodec = nelCodec(codecs.listOfN(codecs.int32, codecs.variableSizeBytes(codecs.int32, eventCodec))) val default = (codecs.ignore(ByteJ.SIZE) ~> eventsCodec) .xmap[Events[A]](a => Events(a, PayloadMetadata.empty), _.events) val version0 = (codecs.constant(ByteVector.fromByte(0)) ~> eventsCodec) .xmap[Events[A]](a => Events(a, PayloadMetadata.empty), _.events) val version1 = (codecs.constant(ByteVector.fromByte(1)) ~> (eventsCodec :: metadataCodec)) .as[Events[A]] codecs.choice(version1, version0, default) } implicit def eventsToBytes[F[_] : FromAttempt, A](implicit eventCodec: Codec[Event[A]], metadataCodec: Codec[PayloadMetadata] ): ToBytes[F, Events[A]] = ToBytes.fromEncoder implicit def eventsFromBytes[F[_] : FromAttempt, A](implicit eventCodec: Codec[Event[A]], metadataCodec: Codec[PayloadMetadata] ): FromBytes[F, Events[A]] = FromBytes.fromDecoder }
Example 166
Source File: ConsRecord.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal import com.evolutiongaming.skafka.consumer.{ConsumerRecord, WithSize} import com.evolutiongaming.skafka.{Header, Offset, TimestampAndType, TopicPartition} import scodec.bits.ByteVector object ConsRecord { def apply( topicPartition: TopicPartition, offset: Offset, timestampAndType: Option[TimestampAndType], key: Option[WithSize[String]] = None, value: Option[WithSize[ByteVector]] = None, headers: List[Header] = Nil ): ConsRecord = { ConsumerRecord( topicPartition = topicPartition, offset = offset, timestampAndType = timestampAndType, key = key, value = value, headers = headers) } }
Example 167
Source File: EventualPayloadAndType.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.eventual import cats.Applicative import cats.implicits._ import com.evolutiongaming.kafka.journal.PayloadType import com.evolutiongaming.kafka.journal.util.Fail import com.evolutiongaming.kafka.journal.util.Fail.implicits._ import scodec.bits.ByteVector final case class EventualPayloadAndType( payload: Either[String, ByteVector], payloadType: PayloadType ) object EventualPayloadAndType { implicit class EventualPayloadAndTypeOps(val self: EventualPayloadAndType) extends AnyVal { def payloadStr[F[_] : Applicative : Fail]: F[String] = self.payload.fold( _.pure[F], _ => "String expected, but got bytes".fail ) def payloadBytes[F[_] : Applicative : Fail]: F[ByteVector] = self.payload.fold( _ => "Bytes expected, but got string".fail, _.pure[F] ) } }
Example 168
Source File: ScodecHelper.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.util import cats.MonadError import cats.data.{NonEmptyList => Nel} import cats.implicits._ import com.evolutiongaming.kafka.journal.JsonCodec import play.api.libs.json.Format import scodec.bits.ByteVector import scodec.{Attempt, Codec, Err, codecs} import scala.annotation.tailrec import scala.util.Try object ScodecHelper { implicit val attemptMonadError: MonadError[Attempt, Attempt.Failure] = { import Attempt._ new MonadError[Attempt, Failure] { def raiseError[A](a: Failure) = a def handleErrorWith[A](fa: Attempt[A])(f: Failure => Attempt[A]) = { fa match { case fa: Successful[A] => fa case fa: Failure => f(fa) } } def pure[A](a: A) = Successful(a) def flatMap[A, B](fa: Attempt[A])(f: A => Attempt[B]) = fa.flatMap(f) @tailrec def tailRecM[A, B](a: A)(f: A => Attempt[Either[A, B]]): Attempt[B] = { f(a) match { case b: Failure => b case b: Successful[Either[A, B]] => b.value match { case Left(b1) => tailRecM(b1)(f) case Right(a) => Successful(a) } } } } } def nelCodec[A](codec: Codec[List[A]]): Codec[Nel[A]] = { val to = (a: List[A]) => { Attempt.fromOption(a.toNel, Err("list is empty")) } val from = (a: Nel[A]) => Attempt.successful(a.toList) codec.exmap(to, from) } def formatCodec[A](implicit format: Format[A], jsonCodec: JsonCodec[Try]): Codec[A] = { val fromBytes = (bytes: ByteVector) => { val jsValue = jsonCodec.decode.fromBytes(bytes) for { a <- Attempt.fromTry(jsValue) a <- format.reads(a).fold(a => Attempt.failure(Err(a.toString())), Attempt.successful) } yield a } val toBytes = (a: A) => { val jsValue = format.writes(a) val bytes = jsonCodec.encode.toBytes(jsValue) Attempt.fromTry(bytes) } codecs.bytes.exmap(fromBytes, toBytes) } }