🔥 Remove duplicate code

This commit is contained in:
Christian Basler 2018-05-31 22:33:26 +02:00
parent fafabf64a3
commit 37cda3df56
3 changed files with 89 additions and 102 deletions

View File

@ -62,13 +62,13 @@ object V3MessageFactory {
fun getPayload(command: String, stream: InputStream, length: Int): MessagePayload? = when (command) { fun getPayload(command: String, stream: InputStream, length: Int): MessagePayload? = when (command) {
"version" -> parseVersion(stream) "version" -> parseVersion(stream)
"verack" -> VerAck() "verack" -> VerAck()
"addr" -> parseAddr(stream) "addr" -> Addr(parseList(stream) { parseAddress(it, false) })
"inv" -> parseInv(stream) "inv" -> Inv(parseList(stream) { parseInventoryVector(it) })
"getdata" -> parseGetData(stream) "getdata" -> GetData(parseList(stream) { parseInventoryVector(it) })
"object" -> readObject(stream, length) "object" -> readObject(stream, length)
"custom" -> readCustom(stream, length) "custom" -> readCustom(stream, length)
else -> { else -> {
LOG.debug("Unknown command: " + command) LOG.debug("Unknown command: $command")
null null
} }
} }
@ -85,73 +85,40 @@ object V3MessageFactory {
val stream = Decode.varInt(input, counter) val stream = Decode.varInt(input, counter)
val data = Decode.bytes(input, length - counter.length()) val data = Decode.bytes(input, length - counter.length())
var payload: ObjectPayload val payload: ObjectPayload = try {
try { Factory.getObjectPayload(objectType, version, stream, ByteArrayInputStream(data), data.size)
val dataStream = ByteArrayInputStream(data)
payload = Factory.getObjectPayload(objectType, version, stream, dataStream, data.size)
} catch (e: Exception) { } catch (e: Exception) {
if (LOG.isTraceEnabled) { if (LOG.isTraceEnabled) {
LOG.trace("Could not parse object payload - using generic payload instead", e) LOG.trace("Could not parse object payload - using generic payload instead", e)
LOG.trace(Strings.hex(data)) LOG.trace(Strings.hex(data))
} }
payload = GenericPayload(version, stream, data) GenericPayload(version, stream, data)
} }
return ObjectMessage.Builder() return ObjectMessage(
.nonce(nonce) nonce, expiresTime, payload, objectType, version, stream
.expiresTime(expiresTime) )
.objectType(objectType)
.stream(stream)
.payload(payload)
.build()
} }
private fun parseGetData(stream: InputStream): GetData { private fun <T> parseList(stream: InputStream, reader: (InputStream) -> (T)): List<T> {
val count = Decode.varInt(stream) val count = Decode.varInt(stream)
val inventoryVectors = LinkedList<InventoryVector>() val items = LinkedList<T>()
for (i in 0 until count) { for (i in 0 until count) {
inventoryVectors.add(parseInventoryVector(stream)) items.add(reader(stream))
} }
return GetData(inventoryVectors) return items
} }
private fun parseInv(stream: InputStream): Inv { private fun parseVersion(stream: InputStream) = Version(
val count = Decode.varInt(stream) version = Decode.int32(stream),
val inventoryVectors = LinkedList<InventoryVector>() services = Decode.int64(stream),
for (i in 0 until count) { timestamp = Decode.int64(stream),
inventoryVectors.add(parseInventoryVector(stream)) addrRecv = parseAddress(stream, true),
} addrFrom = parseAddress(stream, true),
return Inv(inventoryVectors) nonce = Decode.int64(stream),
} userAgent = Decode.varString(stream),
streams = Decode.varIntList(stream)
private fun parseAddr(stream: InputStream): Addr { )
val count = Decode.varInt(stream)
val networkAddresses = LinkedList<NetworkAddress>()
for (i in 0 until count) {
networkAddresses.add(parseAddress(stream, false))
}
return Addr(networkAddresses)
}
private fun parseVersion(stream: InputStream): Version {
val version = Decode.int32(stream)
val services = Decode.int64(stream)
val timestamp = Decode.int64(stream)
val addrRecv = parseAddress(stream, true)
val addrFrom = parseAddress(stream, true)
val nonce = Decode.int64(stream)
val userAgent = Decode.varString(stream)
val streamNumbers = Decode.varIntList(stream)
return Version.Builder()
.version(version)
.services(services)
.timestamp(timestamp)
.addrRecv(addrRecv).addrFrom(addrFrom)
.nonce(nonce)
.userAgent(userAgent)
.streams(*streamNumbers).build()
}
private fun parseInventoryVector(stream: InputStream) = InventoryVector(Decode.bytes(stream, 32)) private fun parseInventoryVector(stream: InputStream) = InventoryVector(Decode.bytes(stream, 32))
@ -168,13 +135,10 @@ object V3MessageFactory {
val services = Decode.int64(stream) val services = Decode.int64(stream)
val ipv6 = Decode.bytes(stream, 16) val ipv6 = Decode.bytes(stream, 16)
val port = Decode.uint16(stream) val port = Decode.uint16(stream)
return NetworkAddress.Builder()
.time(time) return NetworkAddress(
.stream(streamNumber) time, streamNumber, services, ipv6, port
.services(services) )
.ipv6(ipv6)
.port(port)
.build()
} }
private fun testChecksum(checksum: ByteArray, payload: ByteArray): Boolean { private fun testChecksum(checksum: ByteArray, payload: ByteArray): Boolean {

View File

@ -36,12 +36,16 @@ import javax.crypto.spec.SecretKeySpec
/** /**
* Implements everything that isn't directly dependent on either Spongy- or Bouncycastle. * Implements everything that isn't directly dependent on either Spongy- or Bouncycastle.
*/ */
abstract class AbstractCryptography protected constructor(@JvmField protected val provider: Provider) : Cryptography, InternalContext.ContextHolder { abstract class AbstractCryptography protected constructor(@JvmField protected val provider: Provider) : Cryptography,
InternalContext.ContextHolder {
private lateinit var ctx: InternalContext private lateinit var ctx: InternalContext
@JvmField protected val ALGORITHM_ECDSA = "ECDSA" @JvmField
@JvmField protected val ALGORITHM_ECDSA_SHA1 = "SHA1withECDSA" protected val ALGORITHM_ECDSA = "ECDSA"
@JvmField protected val ALGORITHM_EVP_SHA256 = "SHA256withECDSA" @JvmField
protected val ALGORITHM_ECDSA_SHA1 = "SHA1withECDSA"
@JvmField
protected val ALGORITHM_EVP_SHA256 = "SHA256withECDSA"
override fun setContext(context: InternalContext) { override fun setContext(context: InternalContext) {
ctx = context ctx = context
@ -65,8 +69,12 @@ abstract class AbstractCryptography protected constructor(@JvmField protected va
return mda.digest(mda.digest()) return mda.digest(mda.digest())
} }
override fun doubleSha512(data: ByteArray, length: Int): ByteArray { override fun doubleSha512(data: ByteArray, length: Int) = doubleHash("SHA-512", data, length);
val mda = md("SHA-512")
override fun doubleSha256(data: ByteArray, length: Int) = doubleHash("SHA-256", data, length);
private fun doubleHash(method: String, data: ByteArray, length: Int): ByteArray {
val mda = md(method)
mda.update(data, 0, length) mda.update(data, 0, length)
return mda.digest(mda.digest()) return mda.digest(mda.digest())
} }
@ -75,12 +83,6 @@ abstract class AbstractCryptography protected constructor(@JvmField protected va
return hash("RIPEMD160", *data) return hash("RIPEMD160", *data)
} }
override fun doubleSha256(data: ByteArray, length: Int): ByteArray {
val mda = md("SHA-256")
mda.update(data, 0, length)
return mda.digest(mda.digest())
}
override fun sha1(vararg data: ByteArray): ByteArray { override fun sha1(vararg data: ByteArray): ByteArray {
return hash("SHA-1", *data) return hash("SHA-1", *data)
} }
@ -91,13 +93,17 @@ abstract class AbstractCryptography protected constructor(@JvmField protected va
return result return result
} }
override fun doProofOfWork(objectMessage: ObjectMessage, nonceTrialsPerByte: Long, override fun doProofOfWork(
extraBytes: Long, callback: ProofOfWorkEngine.Callback) { objectMessage: ObjectMessage, nonceTrialsPerByte: Long,
extraBytes: Long, callback: ProofOfWorkEngine.Callback
) {
val initialHash = getInitialHash(objectMessage) val initialHash = getInitialHash(objectMessage)
val target = getProofOfWorkTarget(objectMessage, val target = getProofOfWorkTarget(
max(nonceTrialsPerByte, NETWORK_NONCE_TRIALS_PER_BYTE), max(extraBytes, NETWORK_EXTRA_BYTES)) objectMessage,
max(nonceTrialsPerByte, NETWORK_NONCE_TRIALS_PER_BYTE), max(extraBytes, NETWORK_EXTRA_BYTES)
)
ctx.proofOfWorkEngine.calculateNonce(initialHash, target, callback) ctx.proofOfWorkEngine.calculateNonce(initialHash, target, callback)
} }
@ -105,7 +111,10 @@ abstract class AbstractCryptography protected constructor(@JvmField protected va
@Throws(InsufficientProofOfWorkException::class) @Throws(InsufficientProofOfWorkException::class)
override fun checkProofOfWork(objectMessage: ObjectMessage, nonceTrialsPerByte: Long, extraBytes: Long) { override fun checkProofOfWork(objectMessage: ObjectMessage, nonceTrialsPerByte: Long, extraBytes: Long) {
val target = getProofOfWorkTarget(objectMessage, nonceTrialsPerByte, extraBytes) val target = getProofOfWorkTarget(objectMessage, nonceTrialsPerByte, extraBytes)
val value = doubleSha512(objectMessage.nonce ?: throw ApplicationException("Object without nonce"), getInitialHash(objectMessage)) val value = doubleSha512(
objectMessage.nonce ?: throw ApplicationException("Object without nonce"),
getInitialHash(objectMessage)
)
if (Bytes.lt(target, value, 8)) { if (Bytes.lt(target, value, 8)) {
throw InsufficientProofOfWorkException(target, value) throw InsufficientProofOfWorkException(target, value)
} }
@ -136,7 +145,11 @@ abstract class AbstractCryptography protected constructor(@JvmField protected va
return sha512(objectMessage.payloadBytesWithoutNonce) return sha512(objectMessage.payloadBytesWithoutNonce)
} }
override fun getProofOfWorkTarget(objectMessage: ObjectMessage, nonceTrialsPerByte: Long, extraBytes: Long): ByteArray { override fun getProofOfWorkTarget(
objectMessage: ObjectMessage,
nonceTrialsPerByte: Long,
extraBytes: Long
): ByteArray {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val nonceTrialsPerByte = if (nonceTrialsPerByte == 0L) NETWORK_NONCE_TRIALS_PER_BYTE else nonceTrialsPerByte val nonceTrialsPerByte = if (nonceTrialsPerByte == 0L) NETWORK_NONCE_TRIALS_PER_BYTE else nonceTrialsPerByte
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
@ -181,12 +194,16 @@ abstract class AbstractCryptography protected constructor(@JvmField protected va
} }
override fun createPubkey(version: Long, stream: Long, privateSigningKey: ByteArray, privateEncryptionKey: ByteArray, override fun createPubkey(
nonceTrialsPerByte: Long, extraBytes: Long, vararg features: Pubkey.Feature): Pubkey { version: Long, stream: Long, privateSigningKey: ByteArray, privateEncryptionKey: ByteArray,
return Factory.createPubkey(version, stream, nonceTrialsPerByte: Long, extraBytes: Long, vararg features: Pubkey.Feature
): Pubkey {
return Factory.createPubkey(
version, stream,
createPublicKey(privateSigningKey), createPublicKey(privateSigningKey),
createPublicKey(privateEncryptionKey), createPublicKey(privateEncryptionKey),
nonceTrialsPerByte, extraBytes, *features) nonceTrialsPerByte, extraBytes, *features
)
} }
override fun keyToBigInt(privateKey: ByteArray): BigInteger { override fun keyToBigInt(privateKey: ByteArray): BigInteger {

View File

@ -32,15 +32,11 @@ import java.util.*
class JdbcAddressRepository(config: JdbcConfig) : JdbcHelper(config), AddressRepository { class JdbcAddressRepository(config: JdbcConfig) : JdbcHelper(config), AddressRepository {
override fun findContact(ripeOrTag: ByteArray) = find("private_key is null").firstOrNull { override fun findContact(ripeOrTag: ByteArray) = find("private_key is null").getByRipeOrTag(ripeOrTag)
if (it.version > 3) {
Arrays.equals(ripeOrTag, it.tag)
} else {
Arrays.equals(ripeOrTag, it.ripe)
}
}
override fun findIdentity(ripeOrTag: ByteArray) = find("private_key is not null").firstOrNull { override fun findIdentity(ripeOrTag: ByteArray) = find("private_key is not null").getByRipeOrTag(ripeOrTag)
private fun List<BitmessageAddress>.getByRipeOrTag(ripeOrTag: ByteArray): BitmessageAddress? = firstOrNull {
if (it.version > 3) { if (it.version > 3) {
Arrays.equals(ripeOrTag, it.tag) Arrays.equals(ripeOrTag, it.tag)
} else { } else {
@ -67,11 +63,13 @@ class JdbcAddressRepository(config: JdbcConfig) : JdbcHelper(config), AddressRep
try { try {
config.getConnection().use { connection -> config.getConnection().use { connection ->
connection.createStatement().use { stmt -> connection.createStatement().use { stmt ->
stmt.executeQuery(""" stmt.executeQuery(
"""
SELECT address, alias, public_key, private_key, subscribed, chan SELECT address, alias, public_key, private_key, subscribed, chan
FROM Address FROM Address
WHERE $where WHERE $where
""").use { rs -> """
).use { rs ->
while (rs.next()) { while (rs.next()) {
val address: BitmessageAddress val address: BitmessageAddress
@ -79,8 +77,10 @@ class JdbcAddressRepository(config: JdbcConfig) : JdbcHelper(config), AddressRep
if (privateKeyStream == null) { if (privateKeyStream == null) {
address = BitmessageAddress(rs.getString("address")) address = BitmessageAddress(rs.getString("address"))
rs.getBlob("public_key")?.let { publicKeyBlob -> rs.getBlob("public_key")?.let { publicKeyBlob ->
var pubkey: Pubkey = Factory.readPubkey(address.version, address.stream, var pubkey: Pubkey = Factory.readPubkey(
publicKeyBlob.binaryStream, publicKeyBlob.length().toInt(), false)!! address.version, address.stream,
publicKeyBlob.binaryStream, publicKeyBlob.length().toInt(), false
)!!
if (address.version == 4L && pubkey is V3Pubkey) { if (address.version == 4L && pubkey is V3Pubkey) {
pubkey = V4Pubkey(pubkey) pubkey = V4Pubkey(pubkey)
} }
@ -109,8 +109,10 @@ class JdbcAddressRepository(config: JdbcConfig) : JdbcHelper(config), AddressRep
private fun exists(address: BitmessageAddress): Boolean { private fun exists(address: BitmessageAddress): Boolean {
config.getConnection().use { connection -> config.getConnection().use { connection ->
connection.createStatement().use { stmt -> connection.createStatement().use { stmt ->
stmt.executeQuery("SELECT '1' FROM Address " + stmt.executeQuery(
"WHERE address='" + address.address + "'").use { rs -> return rs.next() } "SELECT '1' FROM Address " +
"WHERE address='" + address.address + "'"
).use { rs -> return rs.next() }
} }
} }
} }
@ -159,7 +161,8 @@ class JdbcAddressRepository(config: JdbcConfig) : JdbcHelper(config), AddressRep
private fun insert(address: BitmessageAddress) { private fun insert(address: BitmessageAddress) {
config.getConnection().use { connection -> config.getConnection().use { connection ->
connection.prepareStatement( connection.prepareStatement(
"INSERT INTO Address (address, version, alias, public_key, private_key, subscribed, chan) " + "VALUES (?, ?, ?, ?, ?, ?, ?)").use { ps -> "INSERT INTO Address (address, version, alias, public_key, private_key, subscribed, chan) " + "VALUES (?, ?, ?, ?, ?, ?, ?)"
).use { ps ->
ps.setString(1, address.address) ps.setString(1, address.address)
ps.setLong(2, address.version) ps.setLong(2, address.version)
ps.setString(3, address.alias) ps.setString(3, address.alias)
@ -184,7 +187,10 @@ class JdbcAddressRepository(config: JdbcConfig) : JdbcHelper(config), AddressRep
override fun remove(address: BitmessageAddress) { override fun remove(address: BitmessageAddress) {
try { try {
config.getConnection().use { connection -> connection.createStatement().use { stmt -> stmt.executeUpdate("DELETE FROM Address WHERE address = '" + address.address + "'") } } config.getConnection().use { connection ->
connection.createStatement()
.use { stmt -> stmt.executeUpdate("DELETE FROM Address WHERE address = '" + address.address + "'") }
}
} catch (e: SQLException) { } catch (e: SQLException) {
LOG.error(e.message, e) LOG.error(e.message, e)
} }