Merged in uniqueness-service-tweaks (pull request #98)

Notary tweaks
This commit is contained in:
Andrius Dagys 2016-05-17 12:14:58 +01:00
commit b388fa529f
4 changed files with 33 additions and 6 deletions

View File

@ -99,7 +99,9 @@ class NotaryProtocol(private val wtx: WireTransaction,
}
}
class NotaryException(val error: NotaryError) : Exception()
class NotaryException(val error: NotaryError) : Exception() {
override fun toString() = "${super.toString()}: Error response from Notary - ${error.toString()}"
}
sealed class NotaryError {
class Conflict(val tx: WireTransaction, val conflict: SignedData<UniquenessProvider.Conflict>) : NotaryError() {

View File

@ -43,7 +43,7 @@ object TwoPartyDealProtocol {
val sessionID: Long
)
class SignaturesFromPrimary(val sellerSig: DigitalSignature.WithKey, val notarySig: DigitalSignature.WithKey)
class SignaturesFromPrimary(val sellerSig: DigitalSignature.WithKey, val notarySig: DigitalSignature.LegallyIdentifiable)
/**
* Abstracted bilateral deal protocol participant that initiates communication/handshake.
@ -211,6 +211,8 @@ object TwoPartyDealProtocol {
val signatures = swapSignaturesWithPrimary(stx, handshake.sessionID)
logger.trace { "Got signatures from other party, verifying ... " }
verifyCorrectNotary(stx.tx, signatures.notarySig)
val fullySigned = stx + signatures.sellerSig + signatures.notarySig
fullySigned.verify()
@ -255,6 +257,11 @@ object TwoPartyDealProtocol {
return ptx.toSignedTransaction(checkSufficientSignatures = false)
}
private fun verifyCorrectNotary(wtx: WireTransaction, sig: DigitalSignature.LegallyIdentifiable) {
val notary = serviceHub.loadState(wtx.inputs.first()).notary
check(sig.signer == notary) { "Transaction not signed by the required Notary" }
}
@Suspendable protected abstract fun validateHandshake(handshake: Handshake<U>): Handshake<U>
@Suspendable protected abstract fun assembleSharedTX(handshake: Handshake<U>): Pair<TransactionBuilder, List<PublicKey>>
}

View File

@ -4,7 +4,6 @@ import co.paralleluniverse.fibers.Suspendable
import com.google.common.util.concurrent.ListenableFuture
import contracts.Cash
import contracts.sumCashBy
import core.*
import core.contracts.*
import core.crypto.DigitalSignature
import core.crypto.Party
@ -13,6 +12,8 @@ import core.messaging.SingleMessageRecipient
import core.messaging.StateMachineManager
import core.node.NodeInfo
import core.protocols.ProtocolLogic
import core.random63BitValue
import core.seconds
import core.utilities.ProgressTracker
import core.utilities.trace
import java.security.KeyPair
@ -73,7 +74,7 @@ object TwoPartyTradeProtocol {
)
class SignaturesFromSeller(val sellerSig: DigitalSignature.WithKey,
val notarySig: DigitalSignature.WithKey)
val notarySig: DigitalSignature.LegallyIdentifiable)
open class Seller(val otherSide: SingleMessageRecipient,
val notaryNode: NodeInfo,
@ -215,6 +216,10 @@ object TwoPartyTradeProtocol {
val signatures = swapSignaturesWithSeller(stx, tradeRequest.sessionID)
logger.trace { "Got signatures from seller, verifying ... " }
// TODO: figure out a way to do Notary verification along with other command signatures in SignedTransaction.verify()
verifyCorrectNotary(stx.tx, signatures.notarySig)
val fullySigned = stx + signatures.sellerSig + signatures.notarySig
fullySigned.verify()
@ -270,6 +275,11 @@ object TwoPartyTradeProtocol {
return ptx.toSignedTransaction(checkSufficientSignatures = false)
}
private fun verifyCorrectNotary(wtx: WireTransaction, sig: DigitalSignature.LegallyIdentifiable) {
val notary = serviceHub.loadState(wtx.inputs.first()).notary
check(sig.signer == notary) { "Transaction not signed by the required Notary" }
}
private fun assembleSharedTX(tradeRequest: SellerTradeInfo): Pair<TransactionBuilder, List<PublicKey>> {
val ptx = TransactionBuilder()
// Add input and output states for the movement of cash, by using the Cash contract to generate the states.

View File

@ -163,6 +163,9 @@ class TwoPartyTradeProtocolTests {
// OK, now Bob has sent the partial transaction back to Alice and is waiting for Alice's signature.
assertThat(bobNode.storage.checkpointStorage.checkpoints).hasSize(1)
// TODO: remove once validated transactions are persisted to disk
val recordedTransactions = bobNode.storage.validatedTransactions
// .. and let's imagine that Bob's computer has a power cut. He now has nothing now beyond what was on disk.
bobNode.stop()
@ -179,8 +182,11 @@ class TwoPartyTradeProtocolTests {
}
}, BOB.name, BOB_KEY)
// TODO: remove once validated transactions are persisted to disk
bobNode.storage.validatedTransactions.putAll(recordedTransactions)
// Find the future representing the result of this state machine again.
var bobFuture = bobNode.smm.findStateMachines(TwoPartyTradeProtocol.Buyer::class.java).single().second
val bobFuture = bobNode.smm.findStateMachines(TwoPartyTradeProtocol.Buyer::class.java).single().second
// And off we go again.
net.runNetwork()
@ -268,7 +274,9 @@ class TwoPartyTradeProtocolTests {
RecordingMap.Get(bobsFakeCash[1].id),
RecordingMap.Get(bobsFakeCash[2].id),
// Alice notices that Bob's cash txns depend on a third tx she also doesn't know. She asks, Bob answers.
RecordingMap.Get(bobsFakeCash[0].id)
RecordingMap.Get(bobsFakeCash[0].id),
// Bob wants to verify that the tx has been signed by the correct Notary, which requires looking up an input state
RecordingMap.Get(bobsFakeCash[1].id)
)
assertEquals(expected, records)