diff --git a/server/app/com/xsn/explorer/data/anorm/dao/TransactionInputPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/TransactionInputPostgresDAO.scala index 811a998..b2a28e1 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/TransactionInputPostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/TransactionInputPostgresDAO.scala @@ -27,7 +27,7 @@ class TransactionInputPostgresDAO { 'from_txid -> input.fromTxid.string: NamedParameter, 'from_output_index -> input.fromOutputIndex: NamedParameter, 'value -> input.value: NamedParameter, - 'addresses -> input.addresses.map(_.string): NamedParameter) + 'addresses -> input.addresses.map(_.string).toArray: NamedParameter) } val batch = BatchSql( @@ -35,7 +35,7 @@ class TransactionInputPostgresDAO { |INSERT INTO transaction_inputs | (txid, index, from_txid, from_output_index, value, addresses) |VALUES - | ({txid}, {index}, {from_txid}, {from_output_index}, {value}, ARRAY[{addresses}]::TEXT[]) + | ({txid}, {index}, {from_txid}, {from_output_index}, {value}, {addresses}) """.stripMargin, params.head, params.tail: _* diff --git a/server/app/com/xsn/explorer/data/anorm/dao/TransactionOutputPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/TransactionOutputPostgresDAO.scala index 2fc3aca..fb4801a 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/TransactionOutputPostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/TransactionOutputPostgresDAO.scala @@ -52,7 +52,7 @@ class TransactionOutputPostgresDAO { 'txid -> output.txid.string: NamedParameter, 'index -> output.index: NamedParameter, 'value -> output.value: NamedParameter, - 'addresses -> output.addresses.map(_.string): NamedParameter, + 'addresses -> output.addresses.map(_.string).toArray: NamedParameter, 'hex_script -> output.script.string: NamedParameter) } @@ -61,7 +61,7 @@ class TransactionOutputPostgresDAO { |INSERT INTO transaction_outputs | (txid, index, value, addresses, hex_script) |VALUES - | ({txid}, {index}, {value}, ARRAY[{addresses}]::TEXT[], {hex_script}) + | ({txid}, {index}, {value}, {addresses}, {hex_script}) """.stripMargin, params.head, params.tail: _* diff --git a/server/app/com/xsn/explorer/data/anorm/parsers/CommonParsers.scala b/server/app/com/xsn/explorer/data/anorm/parsers/CommonParsers.scala index d0b2cf8..c8c9a72 100644 --- a/server/app/com/xsn/explorer/data/anorm/parsers/CommonParsers.scala +++ b/server/app/com/xsn/explorer/data/anorm/parsers/CommonParsers.scala @@ -10,15 +10,19 @@ object CommonParsers { .map { _.getOrElse(throw new RuntimeException(s"corrupted $field")) } def parseAddress(field: String = "address") = str(field) - .map(Address.from) - .map { _.getOrElse(throw new RuntimeException(s"corrupted $field")) } + .map { string => + Address.from(string) match { + case None => throw new RuntimeException(s"Corrupted $field: $string") + case Some(address) => address + } + } def parseAddresses = array[String]("addresses") .map { array => array .map { string => Address.from(string) match { - case None => throw new RuntimeException("Corrupted address") + case None => throw new RuntimeException(s"Corrupted address: $string") case Some(address) => address } } diff --git a/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala index 703b8ad..1c2110c 100644 --- a/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala @@ -12,9 +12,10 @@ import com.xsn.explorer.models._ import com.xsn.explorer.models.fields.TransactionField import com.xsn.explorer.models.persisted.Transaction import com.xsn.explorer.models.rpc.Block -import com.xsn.explorer.models.values.{Height, _} +import com.xsn.explorer.models.values._ import org.scalactic.{Bad, Good, One, Or} import org.scalatest.BeforeAndAfter +import org.scalatest.EitherValues._ class TransactionPostgresDataHandlerSpec extends PostgresDataHandlerSpec with BeforeAndAfter { @@ -129,6 +130,22 @@ class TransactionPostgresDataHandlerSpec extends PostgresDataHandlerSpec with Be val result = dataHandler.getOutput(txid, index) result must be(Bad(TransactionNotFoundError).accumulating) } + + "not corrupt the output" in { + val txid = createTransactionId("9969603dca74d14d29d1d5f56b94c7872551607f8c2d6837ab9715c60721b50e") + val rpcTx = TransactionLoader.getWithValues(txid.string).copy(blockhash = block.hash) + val tx = Transaction.fromRPC(rpcTx)._1 + val expected = Transaction.Output( + txid = txid, + index = 2, + value = 0.01, + addresses = List.empty, + script = HexString.from("0804678afd04678afd75a820894eeb82f9a851f5d1cb1be3249f58bc8d259963832c5e7474a76f7a859ee95c87").get) + + upsertTransaction(tx) + val result = dataHandler.getOutput(txid, 2) + result.toEither.right.value must be(expected) + } } "getByBlockhash" should { diff --git a/server/test/resources/transactions/9969603dca74d14d29d1d5f56b94c7872551607f8c2d6837ab9715c60721b50e b/server/test/resources/transactions/9969603dca74d14d29d1d5f56b94c7872551607f8c2d6837ab9715c60721b50e new file mode 100644 index 0000000..9f3d7c0 --- /dev/null +++ b/server/test/resources/transactions/9969603dca74d14d29d1d5f56b94c7872551607f8c2d6837ab9715c60721b50e @@ -0,0 +1,53 @@ +{ + "txid": "9969603dca74d14d29d1d5f56b94c7872551607f8c2d6837ab9715c60721b50e", + "hash": "9969603dca74d14d29d1d5f56b94c7872551607f8c2d6837ab9715c60721b50e", + "version": 1, + "size": 312, + "vsize": 312, + "weight": 1248, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 2.83595354, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 0568015a9facccfd09d70d409b6fc1a5546cecc6 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9140568015a9facccfd09d70d409b6fc1a5546cecc688ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1VayNert3x1KzbpzMGt2qdqrAThiRovi8" + ] + } + }, + { + "value": 0.01, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 7f74e1560a03193e6c6782af4b9982eb111061e4 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9147f74e1560a03193e6c6782af4b9982eb111061e488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1CcvqLs2SzckTsKRhpfk2JzPqkiqSkd6Hu" + ] + } + }, + { + "value": 0.01, + "n": 2, + "scriptPubKey": { + "asm": "04678afd04678afd OP_DROP OP_SHA256 894eeb82f9a851f5d1cb1be3249f58bc8d259963832c5e7474a76f7a859ee95c OP_EQUAL", + "hex": "0804678afd04678afd75a820894eeb82f9a851f5d1cb1be3249f58bc8d259963832c5e7474a76f7a859ee95c87", + "type": "nonstandard" + } + } + ], + "hex": "010000000130b9400da79e83ebaf3fbb6c94f8ee0923e8d64c0089b2318fc9e68753a2d141000000008b483045022064e348746df42411ae5b1cab8b07a22736c42a9e58e336cdc8a5757beb929aa70221008419a71d5947f13586f6b28bc69fa185c289a7bffde174817bd5497109e339e2014104a39b9e4fbd213ef24bb9be69de4a118dd0644082e47c01fd9159d38637b83fbcdc115a5d6e970586a012d1cfe3e3a8b1a3d04e763bdc5a071c0e827c0bd834a5ffffffff035a52e710000000001976a9140568015a9facccfd09d70d409b6fc1a5546cecc688ac40420f00000000001976a9147f74e1560a03193e6c6782af4b9982eb111061e488ac40420f00000000002d0804678afd04678afd75a820894eeb82f9a851f5d1cb1be3249f58bc8d259963832c5e7474a76f7a859ee95c8700000000", + "blockhash": "0000000000000c903d611033d7f69368b69552f79bdedead19b53cf585ea780a", + "confirmations": 419994, + "time": 1321752937, + "blocktime": 1321752937 +} \ No newline at end of file