Refactor to utilize Kotlin features
This commit is contained in:
		@@ -37,33 +37,33 @@ import java.util.*
 | 
			
		||||
data class Message constructor(
 | 
			
		||||
    val subject: String,
 | 
			
		||||
    val body: String,
 | 
			
		||||
    val parents: List<InventoryVector>,
 | 
			
		||||
    val files: List<Attachment>
 | 
			
		||||
    val parents: List<InventoryVector> = emptyList(),
 | 
			
		||||
    val files: List<Attachment> = emptyList()
 | 
			
		||||
) : ExtendedEncoding.ExtendedType {
 | 
			
		||||
 | 
			
		||||
    override val type: String = TYPE
 | 
			
		||||
 | 
			
		||||
    override fun pack(): MPMap<MPString, MPType<*>> {
 | 
			
		||||
        val result = MPMap<MPString, MPType<*>>()
 | 
			
		||||
        result.put("".mp, TYPE.mp)
 | 
			
		||||
        result.put("subject".mp, subject.mp)
 | 
			
		||||
        result.put("body".mp, body.mp)
 | 
			
		||||
        result["".mp] = TYPE.mp
 | 
			
		||||
        result["subject".mp] = subject.mp
 | 
			
		||||
        result["body".mp] = body.mp
 | 
			
		||||
 | 
			
		||||
        if (!files.isEmpty()) {
 | 
			
		||||
            val items = MPArray<MPMap<MPString, MPType<*>>>()
 | 
			
		||||
            result.put("files".mp, items)
 | 
			
		||||
            result["files".mp] = items
 | 
			
		||||
            for (file in files) {
 | 
			
		||||
                val item = MPMap<MPString, MPType<*>>()
 | 
			
		||||
                item.put("name".mp, file.name.mp)
 | 
			
		||||
                item.put("data".mp, file.data.mp)
 | 
			
		||||
                item.put("type".mp, file.type.mp)
 | 
			
		||||
                item.put("disposition".mp, file.disposition.name.mp)
 | 
			
		||||
                item["name".mp] = file.name.mp
 | 
			
		||||
                item["data".mp] = file.data.mp
 | 
			
		||||
                item["type".mp] = file.type.mp
 | 
			
		||||
                item["disposition".mp] = file.disposition.name.mp
 | 
			
		||||
                items.add(item)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!parents.isEmpty()) {
 | 
			
		||||
            val items = MPArray<MPBinary>()
 | 
			
		||||
            result.put("parents".mp, items)
 | 
			
		||||
            result["parents".mp] = items
 | 
			
		||||
            for ((hash) in parents) {
 | 
			
		||||
                items.add(mp(*hash))
 | 
			
		||||
            }
 | 
			
		||||
@@ -179,6 +179,6 @@ data class Message constructor(
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val LOG = LoggerFactory.getLogger(Message::class.java)
 | 
			
		||||
 | 
			
		||||
        val TYPE = "message"
 | 
			
		||||
        const val TYPE = "message"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -156,6 +156,16 @@ interface Cryptography {
 | 
			
		||||
    fun doProofOfWork(objectMessage: ObjectMessage, nonceTrialsPerByte: Long,
 | 
			
		||||
                      extraBytes: Long, callback: ProofOfWorkEngine.Callback)
 | 
			
		||||
 | 
			
		||||
    @JvmSynthetic
 | 
			
		||||
    fun doProofOfWork(objectMessage: ObjectMessage, nonceTrialsPerByte: Long,
 | 
			
		||||
                      extraBytes: Long, callback: (ByteArray, ByteArray) -> Unit) {
 | 
			
		||||
        doProofOfWork(objectMessage, nonceTrialsPerByte, extraBytes, object : ProofOfWorkEngine.Callback {
 | 
			
		||||
            override fun onNonceCalculated(initialHash: ByteArray, nonce: ByteArray) {
 | 
			
		||||
                callback.invoke(initialHash, nonce)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param objectMessage      to be checked
 | 
			
		||||
     * *
 | 
			
		||||
 
 | 
			
		||||
@@ -23,16 +23,32 @@ interface ProofOfWorkEngine {
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a nonce, such that the first 8 bytes from sha512(sha512(nonce||initialHash)) represent a unsigned long
 | 
			
		||||
     * smaller than target.
 | 
			
		||||
 | 
			
		||||
     *
 | 
			
		||||
     * @param initialHash the SHA-512 hash of the object to send, sans nonce
 | 
			
		||||
     * *
 | 
			
		||||
     * @param target      the target, representing an unsigned long
 | 
			
		||||
     * *
 | 
			
		||||
     * @param callback    called with the calculated nonce as argument. The ProofOfWorkEngine implementation must make
 | 
			
		||||
     * *                    sure this is only called once.
 | 
			
		||||
     * @param callback    called with the initial hash and the calculated nonce as argument. The ProofOfWorkEngine
 | 
			
		||||
     *                    implementation must make sure this is only called once.
 | 
			
		||||
     */
 | 
			
		||||
    fun calculateNonce(initialHash: ByteArray, target: ByteArray, callback: Callback)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a nonce, such that the first 8 bytes from sha512(sha512(nonce||initialHash)) represent a unsigned long
 | 
			
		||||
     * smaller than target.
 | 
			
		||||
     *
 | 
			
		||||
     * @param initialHash the SHA-512 hash of the object to send, sans nonce
 | 
			
		||||
     * @param target      the target, representing an unsigned long
 | 
			
		||||
     * @param callback    called with the initial hash and the calculated nonce as argument. The ProofOfWorkEngine
 | 
			
		||||
     *                    implementation must make sure this is only called once.
 | 
			
		||||
     */
 | 
			
		||||
    @JvmSynthetic
 | 
			
		||||
    fun calculateNonce(initialHash: ByteArray, target: ByteArray, callback: (ByteArray, ByteArray) -> Unit) {
 | 
			
		||||
        calculateNonce(initialHash, target, object : Callback {
 | 
			
		||||
            override fun onNonceCalculated(initialHash: ByteArray, nonce: ByteArray) {
 | 
			
		||||
                callback.invoke(initialHash, nonce)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    interface Callback {
 | 
			
		||||
        /**
 | 
			
		||||
         * @param nonce 8 bytes nonce
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ class BitmessageContextTest {
 | 
			
		||||
        ctx.addContact(contact)
 | 
			
		||||
 | 
			
		||||
        verify(ctx.addresses, timeout(1000).atLeastOnce()).save(eq(contact))
 | 
			
		||||
        verify(testPowEngine, timeout(1000)).calculateNonce(any(), any(), any())
 | 
			
		||||
        verify(testPowEngine, timeout(1000)).calculateNonce(any(), any(), any<ProofOfWorkEngine.Callback>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -139,7 +139,7 @@ class BitmessageContextTest {
 | 
			
		||||
        ctx.addContact(contact)
 | 
			
		||||
 | 
			
		||||
        verify(ctx.addresses, times(1)).save(contact)
 | 
			
		||||
        verify(testPowEngine, never()).calculateNonce(any(), any(), any())
 | 
			
		||||
        verify(testPowEngine, never()).calculateNonce(any(), any(), any<ProofOfWorkEngine.Callback>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -162,7 +162,7 @@ class BitmessageContextTest {
 | 
			
		||||
        ctx.addContact(contact)
 | 
			
		||||
 | 
			
		||||
        verify(ctx.addresses, atLeastOnce()).save(contact)
 | 
			
		||||
        verify(testPowEngine, never()).calculateNonce(any(), any(), any())
 | 
			
		||||
        verify(testPowEngine, never()).calculateNonce(any(), any(), any<ProofOfWorkEngine.Callback>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -186,7 +186,7 @@ class BitmessageContextTest {
 | 
			
		||||
        ctx.addContact(contact)
 | 
			
		||||
 | 
			
		||||
        verify(ctx.addresses, atLeastOnce()).save(any())
 | 
			
		||||
        verify(testPowEngine, never()).calculateNonce(any(), any(), any())
 | 
			
		||||
        verify(testPowEngine, never()).calculateNonce(any(), any(), any<ProofOfWorkEngine.Callback>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -245,7 +245,7 @@ class BitmessageContextTest {
 | 
			
		||||
            "Subject", "Message")
 | 
			
		||||
        verify(ctx.internals.proofOfWorkRepository, timeout(1000).atLeastOnce())
 | 
			
		||||
            .putObject(argThat { payload.type == ObjectType.BROADCAST }, eq(1000L), eq(1000L))
 | 
			
		||||
        verify(testPowEngine).calculateNonce(any(), any(), any())
 | 
			
		||||
        verify(testPowEngine).calculateNonce(any(), any(), any<ProofOfWorkEngine.Callback>())
 | 
			
		||||
        verify(ctx.messages, timeout(10000).atLeastOnce()).save(argThat<Plaintext> { type == Type.BROADCAST })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ import ch.dissem.bitmessage.entity.Plaintext.Type.MSG
 | 
			
		||||
import ch.dissem.bitmessage.entity.payload.GenericPayload
 | 
			
		||||
import ch.dissem.bitmessage.entity.payload.Msg
 | 
			
		||||
import ch.dissem.bitmessage.ports.Cryptography
 | 
			
		||||
import ch.dissem.bitmessage.ports.ProofOfWorkEngine
 | 
			
		||||
import ch.dissem.bitmessage.ports.ProofOfWorkRepository
 | 
			
		||||
import ch.dissem.bitmessage.utils.Singleton
 | 
			
		||||
import ch.dissem.bitmessage.utils.TestUtils
 | 
			
		||||
@@ -65,11 +66,11 @@ class ProofOfWorkServiceTest {
 | 
			
		||||
    fun `ensure missing proof of work is done`() {
 | 
			
		||||
        whenever(ctx.proofOfWorkRepository.getItems()).thenReturn(Arrays.asList<ByteArray>(ByteArray(64)))
 | 
			
		||||
        whenever(ctx.proofOfWorkRepository.getItem(any())).thenReturn(ProofOfWorkRepository.Item(obj, 1001, 1002))
 | 
			
		||||
        doNothing().whenever(cryptography).doProofOfWork(any(), any(), any(), any())
 | 
			
		||||
        doNothing().whenever(cryptography).doProofOfWork(any(), any(), any(), any<ProofOfWorkEngine.Callback>())
 | 
			
		||||
 | 
			
		||||
        ctx.proofOfWorkService.doMissingProofOfWork(10)
 | 
			
		||||
 | 
			
		||||
        verify(cryptography, timeout(1000)).doProofOfWork(eq(obj), eq(1001L), eq(1002L), any())
 | 
			
		||||
        verify(cryptography, timeout(1000)).doProofOfWork(eq(obj), eq(1001L), eq(1002L), any<ProofOfWorkEngine.Callback>())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
 
 | 
			
		||||
@@ -89,12 +89,7 @@ class CryptographyTest {
 | 
			
		||||
            stream = 1
 | 
			
		||||
        )
 | 
			
		||||
        val waiter = CallbackWaiter<ByteArray>()
 | 
			
		||||
        crypto.doProofOfWork(objectMessage, 1000, 1000,
 | 
			
		||||
            object : ProofOfWorkEngine.Callback {
 | 
			
		||||
                override fun onNonceCalculated(initialHash: ByteArray, nonce: ByteArray) {
 | 
			
		||||
                    waiter.setValue(nonce)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        crypto.doProofOfWork(objectMessage, 1000, 1000) { _, nonce -> waiter.setValue(nonce) }
 | 
			
		||||
        objectMessage.nonce = waiter.waitForValue()
 | 
			
		||||
        try {
 | 
			
		||||
            crypto.checkProofOfWork(objectMessage, 1000, 1000)
 | 
			
		||||
 
 | 
			
		||||
@@ -42,19 +42,21 @@ import java.io.OutputStream
 | 
			
		||||
 */
 | 
			
		||||
class CryptoCustomMessage<T : Streamable> : CustomMessage {
 | 
			
		||||
 | 
			
		||||
    private val dataReader: Reader<T>?
 | 
			
		||||
    private val dataReader: (BitmessageAddress, InputStream) -> T
 | 
			
		||||
    private var container: CryptoBox? = null
 | 
			
		||||
    var sender: BitmessageAddress? = null
 | 
			
		||||
        private set
 | 
			
		||||
    private var data: T? = null
 | 
			
		||||
        private set
 | 
			
		||||
 | 
			
		||||
    constructor(data: T) : super(COMMAND, null) {
 | 
			
		||||
        this.data = data
 | 
			
		||||
        this.dataReader = null
 | 
			
		||||
        this.dataReader = { _, _ -> data }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private constructor(container: CryptoBox, dataReader: Reader<T>) : super(COMMAND, null) {
 | 
			
		||||
    private constructor(container: CryptoBox, dataReader: (BitmessageAddress, InputStream) -> T) : super(
 | 
			
		||||
        COMMAND,
 | 
			
		||||
        null
 | 
			
		||||
    ) {
 | 
			
		||||
        this.container = container
 | 
			
		||||
        this.dataReader = dataReader
 | 
			
		||||
    }
 | 
			
		||||
@@ -81,8 +83,9 @@ class CryptoCustomMessage<T : Streamable> : CustomMessage {
 | 
			
		||||
 | 
			
		||||
    @Throws(DecryptionFailedException::class)
 | 
			
		||||
    fun decrypt(privateKey: ByteArray): T {
 | 
			
		||||
        val input = SignatureCheckingInputStream(container?.decrypt(privateKey) ?: throw IllegalStateException("no encrypted data available"))
 | 
			
		||||
        if (dataReader == null) throw IllegalStateException("no data reader available")
 | 
			
		||||
        val input = SignatureCheckingInputStream(
 | 
			
		||||
            container?.decrypt(privateKey) ?: throw IllegalStateException("no encrypted data available")
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        val addressVersion = varInt(input)
 | 
			
		||||
        val stream = varInt(input)
 | 
			
		||||
@@ -92,18 +95,20 @@ class CryptoCustomMessage<T : Streamable> : CustomMessage {
 | 
			
		||||
        val nonceTrialsPerByte = if (addressVersion >= 3) varInt(input) else 0
 | 
			
		||||
        val extraBytes = if (addressVersion >= 3) varInt(input) else 0
 | 
			
		||||
 | 
			
		||||
        val sender = BitmessageAddress(Factory.createPubkey(
 | 
			
		||||
            addressVersion,
 | 
			
		||||
            stream,
 | 
			
		||||
            publicSigningKey,
 | 
			
		||||
            publicEncryptionKey,
 | 
			
		||||
            nonceTrialsPerByte,
 | 
			
		||||
            extraBytes,
 | 
			
		||||
            behaviorBitfield
 | 
			
		||||
        ))
 | 
			
		||||
        val sender = BitmessageAddress(
 | 
			
		||||
            Factory.createPubkey(
 | 
			
		||||
                addressVersion,
 | 
			
		||||
                stream,
 | 
			
		||||
                publicSigningKey,
 | 
			
		||||
                publicEncryptionKey,
 | 
			
		||||
                nonceTrialsPerByte,
 | 
			
		||||
                extraBytes,
 | 
			
		||||
                behaviorBitfield
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        this.sender = sender
 | 
			
		||||
 | 
			
		||||
        data = dataReader.read(sender, input)
 | 
			
		||||
        data = dataReader.invoke(sender, input)
 | 
			
		||||
 | 
			
		||||
        input.checkSignature(sender.pubkey!!)
 | 
			
		||||
 | 
			
		||||
@@ -127,7 +132,8 @@ class CryptoCustomMessage<T : Streamable> : CustomMessage {
 | 
			
		||||
        fun read(sender: BitmessageAddress, input: InputStream): T
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private inner class SignatureCheckingInputStream internal constructor(private val wrapped: InputStream) : InputStream() {
 | 
			
		||||
    private inner class SignatureCheckingInputStream internal constructor(private val wrapped: InputStream) :
 | 
			
		||||
        InputStream() {
 | 
			
		||||
        private val out = ByteArrayOutputStream()
 | 
			
		||||
 | 
			
		||||
        override fun read(): Int {
 | 
			
		||||
@@ -145,13 +151,24 @@ class CryptoCustomMessage<T : Streamable> : CustomMessage {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        @JvmField
 | 
			
		||||
        val COMMAND = "ENCRYPTED"
 | 
			
		||||
        const val COMMAND = "ENCRYPTED"
 | 
			
		||||
 | 
			
		||||
        @JvmStatic
 | 
			
		||||
        fun <T : Streamable> read(data: CustomMessage, dataReader: Reader<T>): CryptoCustomMessage<T> {
 | 
			
		||||
            val cryptoBox = CryptoBox.read(ByteArrayInputStream(data.getData()), data.getData().size)
 | 
			
		||||
            return CryptoCustomMessage(cryptoBox, dataReader)
 | 
			
		||||
        }
 | 
			
		||||
        fun <T : Streamable> read(data: CustomMessage, dataReader: Reader<T>): CryptoCustomMessage<T> =
 | 
			
		||||
            CryptoCustomMessage(
 | 
			
		||||
                CryptoBox.read(ByteArrayInputStream(data.getData()), data.getData().size)
 | 
			
		||||
            ) { address, input ->
 | 
			
		||||
                dataReader.read(address, input)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        @JvmSynthetic
 | 
			
		||||
        fun <T : Streamable> read(
 | 
			
		||||
            data: CustomMessage,
 | 
			
		||||
            dataReader: (BitmessageAddress, InputStream) -> T
 | 
			
		||||
        ): CryptoCustomMessage<T> =
 | 
			
		||||
            CryptoCustomMessage(
 | 
			
		||||
                CryptoBox.read(ByteArrayInputStream(data.getData()), data.getData().size),
 | 
			
		||||
                dataReader
 | 
			
		||||
            )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user