mirror of
https://github.com/corda/corda.git
synced 2025-06-16 22:28:15 +00:00
* 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:
@ -20,7 +20,7 @@ import net.corda.core.utilities.unwrap
|
|||||||
abstract class NotaryServiceFlow(val otherSideSession: FlowSession, val service: TrustedAuthorityNotaryService) : FlowLogic<Void?>() {
|
abstract class NotaryServiceFlow(val otherSideSession: FlowSession, val service: TrustedAuthorityNotaryService) : FlowLogic<Void?>() {
|
||||||
companion object {
|
companion object {
|
||||||
// TODO: Determine an appropriate limit and also enforce in the network parameters and the transaction builder.
|
// 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
|
@Suspendable
|
||||||
@ -44,9 +44,10 @@ abstract class NotaryServiceFlow(val otherSideSession: FlowSession, val service:
|
|||||||
|
|
||||||
/** Checks whether the number of input states is too large. */
|
/** Checks whether the number of input states is too large. */
|
||||||
protected fun checkInputs(inputs: List<StateRef>) {
|
protected fun checkInputs(inputs: List<StateRef>) {
|
||||||
if (inputs.size > maxAllowedInputs) {
|
if (inputs.size > maxAllowedInputsAndReferences) {
|
||||||
val error = NotaryError.TransactionInvalid(
|
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)
|
throw NotaryInternalException(error)
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* this method does not throw an exception when input states are present multiple times within the transaction.
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@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 {
|
try {
|
||||||
uniquenessProvider.commit(inputs, txId, caller, requestSignature, timeWindow, references)
|
uniquenessProvider.commit(inputs, txId, caller, requestSignature, timeWindow, references)
|
||||||
} catch (e: NotaryInternalException) {
|
} catch (e: NotaryInternalException) {
|
||||||
|
@ -139,10 +139,11 @@ class BFTNonValidatingNotaryService(
|
|||||||
return try {
|
return try {
|
||||||
val id = transaction.id
|
val id = transaction.id
|
||||||
val inputs = transaction.inputs
|
val inputs = transaction.inputs
|
||||||
|
val references = transaction.references
|
||||||
val notary = transaction.notary
|
val notary = transaction.notary
|
||||||
val timeWindow = (transaction as? FilteredTransaction)?.timeWindow
|
val timeWindow = (transaction as? FilteredTransaction)?.timeWindow
|
||||||
if (notary !in services.myInfo.legalIdentities) throw NotaryInternalException(NotaryError.WrongNotary)
|
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" }
|
log.debug { "Inputs committed successfully, signing $id" }
|
||||||
BFTSMaRt.ReplicaResponse.Signature(sign(id))
|
BFTSMaRt.ReplicaResponse.Signature(sign(id))
|
||||||
} catch (e: NotaryInternalException) {
|
} catch (e: NotaryInternalException) {
|
||||||
|
@ -223,17 +223,35 @@ object BFTSMaRt {
|
|||||||
*/
|
*/
|
||||||
abstract fun executeCommand(command: ByteArray): ByteArray?
|
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" }
|
log.debug { "Attempting to commit inputs for transaction: $txId" }
|
||||||
services.database.transaction {
|
services.database.transaction {
|
||||||
logRequest(txId, callerName, requestSignature)
|
logRequest(txId, callerName, requestSignature)
|
||||||
val conflictingStates = LinkedHashMap<StateRef, StateConsumptionDetails>()
|
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 (conflictingStates.isNotEmpty()) {
|
||||||
if (!isConsumedByTheSameTx(txId.sha256(), conflictingStates)) {
|
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))
|
throw NotaryInternalException(NotaryError.Conflict(txId, conflictingStates))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,7 +24,7 @@ class NonValidatingNotaryFlow(otherSideSession: FlowSession, service: TrustedAut
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun validateRequest(requestPayload: NotarisationPayload): TransactionParts {
|
override fun validateRequest(requestPayload: NotarisationPayload): TransactionParts {
|
||||||
val transaction = requestPayload.coreTransaction
|
val transaction = requestPayload.coreTransaction
|
||||||
checkInputs(transaction.inputs)
|
checkInputs(transaction.inputs + transaction.references)
|
||||||
val request = NotarisationRequest(transaction.inputs, transaction.id)
|
val request = NotarisationRequest(transaction.inputs, transaction.id)
|
||||||
validateRequestSignature(request, requestPayload.requestSignature)
|
validateRequestSignature(request, requestPayload.requestSignature)
|
||||||
val parts = extractParts(transaction)
|
val parts = extractParts(transaction)
|
||||||
|
@ -31,7 +31,7 @@ class ValidatingNotaryFlow(otherSideSession: FlowSession, service: TrustedAuthor
|
|||||||
override fun validateRequest(requestPayload: NotarisationPayload): TransactionParts {
|
override fun validateRequest(requestPayload: NotarisationPayload): TransactionParts {
|
||||||
try {
|
try {
|
||||||
val stx = requestPayload.signedTransaction
|
val stx = requestPayload.signedTransaction
|
||||||
checkInputs(stx.inputs)
|
checkInputs(stx.inputs + stx.references)
|
||||||
validateRequestSignature(NotarisationRequest(stx.inputs, stx.id), requestPayload.requestSignature)
|
validateRequestSignature(NotarisationRequest(stx.inputs, stx.id), requestPayload.requestSignature)
|
||||||
val notary = stx.notary
|
val notary = stx.notary
|
||||||
checkNotary(notary)
|
checkNotary(notary)
|
||||||
|
Reference in New Issue
Block a user