* Minor formatting changes. (#3758)

* NotaryServiceFlow now takes references into account when comparing number of inputs vs maxAllowedInputs.
* Added reference state support for BFTSMaRt notary.

* Fixes broken BFT notary tests.
This commit is contained in:
Roger Willis 2018-08-10 08:51:56 +01:00 committed by GitHub
parent ce5f38104b
commit b0d36b6617
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 12 deletions

View File

@ -20,7 +20,7 @@ import net.corda.core.utilities.unwrap
abstract class NotaryServiceFlow(val otherSideSession: FlowSession, val service: TrustedAuthorityNotaryService) : FlowLogic<Void?>() {
companion object {
// TODO: Determine an appropriate limit and also enforce in the network parameters and the transaction builder.
private const val maxAllowedInputs = 10_000
private const val maxAllowedInputsAndReferences = 10_000
}
@Suspendable
@ -44,9 +44,10 @@ abstract class NotaryServiceFlow(val otherSideSession: FlowSession, val service:
/** Checks whether the number of input states is too large. */
protected fun checkInputs(inputs: List<StateRef>) {
if (inputs.size > maxAllowedInputs) {
if (inputs.size > maxAllowedInputsAndReferences) {
val error = NotaryError.TransactionInvalid(
IllegalArgumentException("A transaction cannot have more than $maxAllowedInputs inputs, received: ${inputs.size}")
IllegalArgumentException("A transaction cannot have more than $maxAllowedInputsAndReferences " +
"inputs or references, received: ${inputs.size}")
)
throw NotaryInternalException(error)
}

View File

@ -26,7 +26,14 @@ abstract class TrustedAuthorityNotaryService : NotaryService() {
* this method does not throw an exception when input states are present multiple times within the transaction.
*/
@JvmOverloads
fun commitInputStates(inputs: List<StateRef>, txId: SecureHash, caller: Party, requestSignature: NotarisationRequestSignature, timeWindow: TimeWindow?, references: List<StateRef> = emptyList()) {
fun commitInputStates(
inputs: List<StateRef>,
txId: SecureHash,
caller: Party,
requestSignature: NotarisationRequestSignature,
timeWindow: TimeWindow?,
references: List<StateRef> = emptyList()
) {
try {
uniquenessProvider.commit(inputs, txId, caller, requestSignature, timeWindow, references)
} catch (e: NotaryInternalException) {

View File

@ -139,10 +139,11 @@ class BFTNonValidatingNotaryService(
return try {
val id = transaction.id
val inputs = transaction.inputs
val references = transaction.references
val notary = transaction.notary
val timeWindow = (transaction as? FilteredTransaction)?.timeWindow
if (notary !in services.myInfo.legalIdentities) throw NotaryInternalException(NotaryError.WrongNotary)
commitInputStates(inputs, id, callerIdentity.name, requestSignature, timeWindow)
commitInputStates(inputs, id, callerIdentity.name, requestSignature, timeWindow, references)
log.debug { "Inputs committed successfully, signing $id" }
BFTSMaRt.ReplicaResponse.Signature(sign(id))
} catch (e: NotaryInternalException) {

View File

@ -223,17 +223,35 @@ object BFTSMaRt {
*/
abstract fun executeCommand(command: ByteArray): ByteArray?
protected fun commitInputStates(states: List<StateRef>, txId: SecureHash, callerName: CordaX500Name, requestSignature: NotarisationRequestSignature, timeWindow: TimeWindow?) {
private fun checkConflict(
conflictingStates: LinkedHashMap<StateRef, StateConsumptionDetails>,
states: List<StateRef>,
type: StateConsumptionDetails.ConsumedStateType
) {
states.forEach { stateRef ->
commitLog[stateRef]?.let { conflictingStates[stateRef] = StateConsumptionDetails(it.sha256(), type) }
}
}
protected fun commitInputStates(
states: List<StateRef>,
txId: SecureHash,
callerName: CordaX500Name,
requestSignature: NotarisationRequestSignature,
timeWindow: TimeWindow?,
references: List<StateRef> = emptyList()
) {
log.debug { "Attempting to commit inputs for transaction: $txId" }
services.database.transaction {
logRequest(txId, callerName, requestSignature)
val conflictingStates = LinkedHashMap<StateRef, StateConsumptionDetails>()
for (state in states) {
commitLog[state]?.let { conflictingStates[state] = StateConsumptionDetails(it.sha256()) }
}
checkConflict(conflictingStates, states, StateConsumptionDetails.ConsumedStateType.INPUT_STATE)
checkConflict(conflictingStates, references, StateConsumptionDetails.ConsumedStateType.REFERENCE_INPUT_STATE)
if (conflictingStates.isNotEmpty()) {
if (!isConsumedByTheSameTx(txId.sha256(), conflictingStates)) {
log.debug { "Failure, input states already committed: ${conflictingStates.keys}" }
log.debug { "Failure, input states or references already committed: ${conflictingStates.keys}" }
throw NotaryInternalException(NotaryError.Conflict(txId, conflictingStates))
}
} else {

View File

@ -24,7 +24,7 @@ class NonValidatingNotaryFlow(otherSideSession: FlowSession, service: TrustedAut
@Suspendable
override fun validateRequest(requestPayload: NotarisationPayload): TransactionParts {
val transaction = requestPayload.coreTransaction
checkInputs(transaction.inputs)
checkInputs(transaction.inputs + transaction.references)
val request = NotarisationRequest(transaction.inputs, transaction.id)
validateRequestSignature(request, requestPayload.requestSignature)
val parts = extractParts(transaction)

View File

@ -31,7 +31,7 @@ class ValidatingNotaryFlow(otherSideSession: FlowSession, service: TrustedAuthor
override fun validateRequest(requestPayload: NotarisationPayload): TransactionParts {
try {
val stx = requestPayload.signedTransaction
checkInputs(stx.inputs)
checkInputs(stx.inputs + stx.references)
validateRequestSignature(NotarisationRequest(stx.inputs, stx.id), requestPayload.requestSignature)
val notary = stx.notary
checkNotary(notary)