Skip to content

Commit

Permalink
update scala dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
h0ngcha0 committed Dec 12, 2020
1 parent 96b0b61 commit 7988fd0
Show file tree
Hide file tree
Showing 27 changed files with 135 additions and 82 deletions.
7 changes: 5 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name := "bitcoin4s"
organization := "it.softfork"
version := "0.1.0"

scalaVersion in ThisBuild := "2.13.4"
scalaVersion in ThisBuild := "2.13.2"

scalacOptions := Seq(
"-unchecked",
Expand All @@ -23,9 +23,12 @@ scalacOptions := Seq(
"-Ymacro-annotations"
)

val akkaHttpVersion = "10.1.12"
val akkaHttpVersion = "10.2.2"
val akkaVersion = "2.6.10"

libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"com.typesafe.akka" %% "akka-stream" % akkaVersion,
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http-core" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http-xml" % akkaHttpVersion,
Expand Down
6 changes: 1 addition & 5 deletions src/main/scala/it/softfork/bitcoin4s/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ object Main extends App with Boot {

import system.dispatcher

val serverFuture = Http().bindAndHandle(
handler = routes(),
interface = "0.0.0.0",
port = 8888
)
val serverFuture = Http().newServerAt("0.0.0.0", 8888).bind(routes())

serverFuture.onComplete {
case Success(Http.ServerBinding(address)) =>
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/it/softfork/bitcoin4s/Routes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Routes(blockcypherService: BlockCypherService)(implicit ec: ExecutionConte
}
} ~
path("stream-interpret") {
extractUpgradeToWebSocket { upgrade =>
extractWebSocketUpgrade { upgrade =>
complete {
val interpretSource = blockcypherService
.interpretStream(txId, inputIndex)
Expand Down
7 changes: 4 additions & 3 deletions src/main/scala/it/softfork/bitcoin4s/Utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import scodec.bits.BitVector
import org.spongycastle.util.encoders.Hex

package object Utils {

implicit class Rich[T](value: T) {
def toHex: String = "%02x".format(value)
}
Expand Down Expand Up @@ -102,17 +103,17 @@ package object Utils {
}

def bytesToUInt8(bytes: Seq[Byte]): Int = {
bytes.head.toShort & 0xFF
bytes.head.toShort & 0xff
}

def bytesToUInt16(bytes: Seq[Byte]): Int = {
val byteBuffer = ByteBuffer.wrap(bytes.toArray).order(ByteOrder.LITTLE_ENDIAN)
byteBuffer.getShort & 0xFFFF
byteBuffer.getShort & 0xffff
}

def bytesToUInt32(bytes: Seq[Byte]): Int = {
val byteBuffer = ByteBuffer.wrap(bytes.toArray).order(ByteOrder.LITTLE_ENDIAN)
byteBuffer.getInt & 0xFFFFFFFF
byteBuffer.getInt & 0xffffffff
}

def uint32ToBytes(input: Long): Array[Byte] = uint32ToBytes(input, ByteOrder.LITTLE_ENDIAN)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/it/softfork/bitcoin4s/crypto/Base58Check.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object Base58Check {
}

case object P2PKHTestnetVersionPrefix extends VersionPrefix {
val value = 0x6F.toByte
val value = 0x6f.toByte
}

case object PrivateKeyWIFVersionPrefix extends VersionPrefix {
Expand All @@ -47,6 +47,6 @@ object Base58Check {
}

case object BIP32ExtendedPublicKeyVersionPrefix extends VersionPrefix {
val value = 0x0488B21E.toByte
val value = 0x0488b21e.toByte
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,14 @@ object TransactionCacheActor {

implicit val timeout: Timeout = Timeout(5.seconds)

def getTransaction(txId: TxId)(
implicit
def getTransaction(txId: TxId)(implicit
ec: ExecutionContext,
transactionCacheActor: ActorRef
): Future[Option[Transaction]] = {
(transactionCacheActor ? Get(txId)).mapTo[Option[Transaction]]
}

def setTransaction(txId: TxId, tx: Transaction)(
implicit
def setTransaction(txId: TxId, tx: Transaction)(implicit
ec: ExecutionContext,
transactionCacheActor: ActorRef
): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,22 @@ import it.softfork.bitcoin4s.transaction.structure.{Hash => ScodecHash}
import it.softfork.bitcoin4s.transaction.{Tx, TxId, TxRaw, TxWitness}
import play.api.libs.json.{Format, JsError, JsSuccess, Json}
import scodec.bits.ByteVector
import it.softfork.bitcoin4s.ApiModels.{scriptElementFormat, Transaction => ApiTransaction, TransactionInput => ApiTransactionInput, TransactionOutput => ApiTransactionOutput}
import it.softfork.bitcoin4s.ApiModels.{
scriptElementFormat,
Transaction => ApiTransaction,
TransactionInput => ApiTransactionInput,
TransactionOutput => ApiTransactionOutput
}

import scala.concurrent.{ExecutionContext, Future}
import it.softfork.bitcoin4s.Utils.hexToBytes
import scodec.bits._

class Api(httpSender: HttpSender)(
implicit
class Api(httpSender: HttpSender)(implicit
ec: ExecutionContext,
materializer: Materializer
) extends ApiInterface {

override def getTransaction(txId: TxId): Future[Option[ApiTransaction]] = {
httpSender(HttpRequest(uri = rawTxUrl(txId))).flatMap { response =>
if (response.status.isSuccess()) {
Expand All @@ -35,8 +40,7 @@ class Api(httpSender: HttpSender)(
}
}

class CachedApi(api: Api)(
implicit
class CachedApi(api: Api)(implicit
system: ActorSystem,
ec: ExecutionContext
) extends ApiInterface {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import it.softfork.bitcoin4s.external.ApiInterface

import scala.collection.immutable.ArraySeq

class Service(api: ApiInterface)(
implicit
class Service(api: ApiInterface)(implicit
ec: ExecutionContext,
materializer: Materializer
) extends StrictLogging {
Expand Down
119 changes: 79 additions & 40 deletions src/main/scala/it/softfork/bitcoin4s/script/ArithmeticOp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,20 @@ object ArithmeticOp {
oneOperant(opCode, (number: ScriptNum) => ScriptNum(Math.abs(number.value)))

case OP_NOT =>
oneOperant(opCode, (number: ScriptNum) => {
(number.value == 0).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
oneOperant(
opCode,
(number: ScriptNum) => {
(number.value == 0).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_0NOTEQUAL =>
oneOperant(opCode, (number: ScriptNum) => {
(number.value == 0).option(ScriptNum(0)).getOrElse(ScriptNum(1))
})
oneOperant(
opCode,
(number: ScriptNum) => {
(number.value == 0).option(ScriptNum(0)).getOrElse(ScriptNum(1))
}
)

case OP_ADD =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => first + second)
Expand All @@ -109,64 +115,97 @@ object ArithmeticOp {
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => second - first)

case OP_BOOLAND =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(first.value =!= 0 && second.value =!= 0).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(first.value =!= 0 && second.value =!= 0).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_BOOLOR =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(first.value =!= 0 || second.value =!= 0).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(first.value =!= 0 || second.value =!= 0).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_NUMEQUAL =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(first.value === second.value).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(first.value === second.value).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_NUMEQUALVERIFY =>
// OP_NUMEQUAL + OP_VERIFY
for {
result <- twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(first.value === second.value).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
result <- twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(first.value === second.value).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)
state <- getState
_ <- setState(state.copy(currentScript = OP_VERIFY +: state.currentScript))
} yield result

case OP_NUMNOTEQUAL =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(first.value =!= second.value).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(first.value =!= second.value).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_LESSTHAN =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(second < first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(second < first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_GREATERTHAN =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(second > first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(second > first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_GREATERTHANOREQUAL =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(second >= first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(second >= first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_LESSTHANOREQUAL =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
(second <= first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
(second <= first).option(ScriptNum(1)).getOrElse(ScriptNum(0))
}
)

case OP_MIN =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
ScriptNum(Math.min(first.value, second.value))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
ScriptNum(Math.min(first.value, second.value))
}
)

case OP_MAX =>
twoOperants(opCode, (first: ScriptNum, second: ScriptNum) => {
ScriptNum(Math.max(first.value, second.value))
})
twoOperants(
opCode,
(first: ScriptNum, second: ScriptNum) => {
ScriptNum(Math.max(first.value, second.value))
}
)

case OP_WITHIN =>
getState.flatMap { state =>
Expand All @@ -180,7 +219,7 @@ object ArithmeticOp {
)
} match {
case Success((firstNumber, secondNumber, thirdNumber)) =>
val isWithin = (thirdNumber < firstNumber && thirdNumber >= secondNumber)
val isWithin = thirdNumber < firstNumber && thirdNumber >= secondNumber
val newState = state.copy(
currentScript = state.currentScript,
stack = isWithin.option(ScriptNum(1)).getOrElse(ScriptNum(0)) +: rest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ object BitwiseLogicOp {
val disabled = Seq(OP_INVERT, OP_AND, OP_OR, OP_XOR)

implicit val interpreter = new InterpretableOp[BitwiseLogicOp] {

override def interpret(opCode: BitwiseLogicOp): InterpreterContext[Option[Boolean]] = {
opCode match {
case opc if disabled.contains(opc) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ object ConstantOp {
// How does this work?

implicit val interpreter = new InterpretableOp[ConstantOp] {

override def interpret(opCode: ConstantOp): InterpreterContext[Option[Boolean]] = {
opCode match {
case opc if opc.value >= 79 && opc.value <= 96 => // From OP_1NEGATE to OP_16
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/it/softfork/bitcoin4s/script/Interpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ object Interpreter {
}

import scala.language.existentials

private def interpretOneOp(state: InterpreterState, verbose: Boolean, steps: Option[Int]) = {
val result = state.currentScript match {
case opCode :: tail =>
Expand Down Expand Up @@ -461,7 +462,7 @@ object Interpreter {
witnessHash.bytes.length match {
case 20 =>
// P2WPKH
val witnessProgramMatch = (Hash.Hash160(head.bytes.toArray).toSeq == witnessHash.bytes)
val witnessProgramMatch = Hash.Hash160(head.bytes.toArray).toSeq == witnessHash.bytes
if (witnessProgramMatch) {
val witnessProgram = OP_DUP :: OP_HASH160 :: OP_PUSHDATA(20) :: witnessHash :: OP_EQUALVERIFY :: OP_CHECKSIG :: Nil
Right((witnessProgram, witnessStack))
Expand All @@ -470,7 +471,7 @@ object Interpreter {
}

case 32 =>
val witnessProgramMatch = (Hash.Sha256(head.bytes.toArray).toSeq == witnessHash.bytes)
val witnessProgramMatch = Hash.Sha256(head.bytes.toArray).toSeq == witnessHash.bytes
if (witnessProgramMatch) {
val witnessProgram = Parser.parse(head.bytes)
Right((witnessProgram, removePushOps(tail)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sealed trait InterpreterError extends RuntimeException with Product {
}

object InterpreterError {

case class BadOpCode(opCode: ScriptOpCode, state: InterpreterState, descriptionIn: String) extends InterpreterError {
override def description = descriptionIn
}
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/it/softfork/bitcoin4s/script/LocktimeOp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,10 @@ object LocktimeOp {
// We want to compare apples to apples, so fail the script
// unless the type of nSequenceMasked being tested is the same as
// the nSequenceMasked in the transaction.
val bothLockByBlockHeight = (txToSequenceMasked < txIn.SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < txIn.SEQUENCE_LOCKTIME_TYPE_FLAG)
val bothLockByBlockTime = (txToSequenceMasked >= txIn.SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= txIn.SEQUENCE_LOCKTIME_TYPE_FLAG)
val bothLockByBlockHeight =
txToSequenceMasked < txIn.SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < txIn.SEQUENCE_LOCKTIME_TYPE_FLAG
val bothLockByBlockTime =
txToSequenceMasked >= txIn.SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= txIn.SEQUENCE_LOCKTIME_TYPE_FLAG
val sameKindOfNSequence = bothLockByBlockHeight || bothLockByBlockTime

transactionVersionNotHighEnough &&
Expand Down
Loading

0 comments on commit 7988fd0

Please sign in to comment.