Changes the name of the addTimeWindow method to setTimeWindow.

This commit is contained in:
Joel Dudley 2017-07-05 10:57:18 +01:00 committed by GitHub
parent 7eaac8a306
commit 65f385953f
18 changed files with 56 additions and 45 deletions

View File

@ -40,7 +40,7 @@ open class TransactionBuilder(
protected val outputs: MutableList<TransactionState<ContractState>> = arrayListOf(),
protected val commands: MutableList<Command> = arrayListOf(),
protected val signers: MutableSet<PublicKey> = mutableSetOf(),
protected var timeWindow: TimeWindow? = null) {
window: TimeWindow? = null) {
constructor(type: TransactionType, notary: Party) : this(type, notary, (Strand.currentStrand() as? FlowStateMachine<*>)?.id?.uuid ?: UUID.randomUUID())
/**
@ -55,7 +55,7 @@ open class TransactionBuilder(
outputs = ArrayList(outputs),
commands = ArrayList(commands),
signers = LinkedHashSet(signers),
timeWindow = timeWindow
window = timeWindow
)
// DOCSTART 1
@ -120,24 +120,27 @@ open class TransactionBuilder(
fun addCommand(data: CommandData, vararg keys: PublicKey) = addCommand(Command(data, listOf(*keys)))
fun addCommand(data: CommandData, keys: List<PublicKey>) = addCommand(Command(data, keys))
var timeWindow: TimeWindow? = window
/**
* Sets the [TimeWindow] for this transaction, replacing the existing [TimeWindow] if there is one. To be valid, the
* transaction must then be signed by the notary service within this window of time. In this way, the notary acts as
* the Timestamp Authority.
*/
set(value) {
check(notary != null) { "Only notarised transactions can have a time-window" }
signers.add(notary!!.owningKey)
field = value
}
/**
* Places a [TimeWindow] in this transaction, removing any existing command if there is one.
* The command requires a signature from the Notary service, which acts as a Timestamp Authority.
* The signature can be obtained using [NotaryFlow].
*
* The window of time in which the final time-window may lie is defined as [time] +/- [timeTolerance].
* If you want a non-symmetrical time window you must add the command via [addCommand] yourself. The tolerance
* should be chosen such that your code can finish building the transaction and sending it to the TSA within that
* window of time, taking into account factors such as network latency. Transactions being built by a group of
* The [TimeWindow] for the transaction can also be defined as [time] +/- [timeTolerance]. The tolerance should be
* chosen such that your code can finish building the transaction and sending it to the Timestamp Authority within
* that window of time, taking into account factors such as network latency. Transactions being built by a group of
* collaborating parties may therefore require a higher time tolerance than a transaction being built by a single
* node.
*/
fun addTimeWindow(time: Instant, timeTolerance: Duration) = addTimeWindow(TimeWindow.withTolerance(time, timeTolerance))
fun addTimeWindow(timeWindow: TimeWindow) {
check(notary != null) { "Only notarised transactions can have a time-window" }
signers.add(notary!!.owningKey)
this.timeWindow = timeWindow
fun setTimeWindow(time: Instant, timeTolerance: Duration) {
timeWindow = TimeWindow.withTolerance(time, timeTolerance)
}
// Accessors that yield immutable snapshots.
@ -200,4 +203,4 @@ open class TransactionBuilder(
require(commands.any { it.signers.any { sig.by in it.keys } }) { "Signature key doesn't match any command" }
sig.verify(toWireTransaction().id)
}
}
}

View File

@ -99,7 +99,7 @@ class TransactionSerializationTests {
@Test
fun timeWindow() {
tx.addTimeWindow(TEST_TX_TIME, 30.seconds)
tx.setTimeWindow(TEST_TX_TIME, 30.seconds)
val ptx = megaCorpServices.signInitialTransaction(tx)
val stx = notaryServices.addSignature(ptx)
assertEquals(TEST_TX_TIME, stx.tx.timeWindow?.midpoint)

View File

@ -30,6 +30,7 @@ import net.corda.flows.SignTransactionFlow;
import org.bouncycastle.asn1.x500.X500Name;
import java.security.PublicKey;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Set;
@ -303,7 +304,10 @@ public class FlowCookbookJava {
regTxBuilder.addOutputState(ourOutput);
regTxBuilder.addCommand(ourCommand);
regTxBuilder.addAttachment(ourAttachment);
regTxBuilder.addTimeWindow(ourTimeWindow);
// We set the time-window within which the transaction must be notarised using either of:
regTxBuilder.setTimeWindow(ourTimeWindow);
regTxBuilder.setTimeWindow(getServiceHub().getClock().instant(), Duration.ofSeconds(30));
/*-----------------------
* TRANSACTION SIGNING *

View File

@ -29,6 +29,7 @@ import net.corda.flows.ResolveTransactionsFlow
import net.corda.flows.SignTransactionFlow
import org.bouncycastle.asn1.x500.X500Name
import java.security.PublicKey
import java.time.Duration
import java.time.Instant
// We group our two flows inside a singleton object to indicate that they work
@ -286,7 +287,10 @@ object FlowCookbook {
regTxBuilder.addOutputState(ourOutput)
regTxBuilder.addCommand(ourCommand)
regTxBuilder.addAttachment(ourAttachment)
regTxBuilder.addTimeWindow(ourTimeWindow)
// We set the time-window within which the transaction must be notarised using either of:
regTxBuilder.timeWindow = ourTimeWindow
regTxBuilder.setTimeWindow(serviceHub.clock.instant(), Duration.ofSeconds(30))
/**----------------------
* TRANSACTION SIGNING *

View File

@ -123,7 +123,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
// Create the TransactionBuilder and populate with the new state.
val tx = TransactionType.General.Builder(notary)
.withItems(tradeProposal, Command(TradeApprovalContract.Commands.Issue(), listOf(tradeProposal.source.owningKey)))
tx.addTimeWindow(serviceHub.clock.instant(), Duration.ofSeconds(60))
tx.setTimeWindow(serviceHub.clock.instant(), Duration.ofSeconds(60))
// We can automatically sign as there is no untrusted data.
val signedTx = serviceHub.signInitialTransaction(tx)
// Notarise and distribute.
@ -184,7 +184,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
newState,
Command(TradeApprovalContract.Commands.Completed(),
listOf(serviceHub.myInfo.legalIdentity.owningKey, latestRecord.state.data.source.owningKey)))
tx.addTimeWindow(serviceHub.clock.instant(), Duration.ofSeconds(60))
tx.setTimeWindow(serviceHub.clock.instant(), Duration.ofSeconds(60))
// We can sign this transaction immediately as we have already checked all the fields and the decision
// is ultimately a manual one from the caller.
// As a SignedTransaction we can pass the data around certain that it cannot be modified,

View File

@ -543,7 +543,7 @@ class Obligation<P : Any> : Contract {
}
tx.addCommand(Commands.SetLifecycle(lifecycle), partiesUsed.map { it.owningKey }.distinct())
}
tx.addTimeWindow(issuanceDef.dueBefore, issuanceDef.timeTolerance)
tx.setTimeWindow(issuanceDef.dueBefore, issuanceDef.timeTolerance)
}
/**

View File

@ -183,9 +183,9 @@ object TwoPartyDealFlow {
val deal = handshake.payload.dealBeingOffered
val ptx = deal.generateAgreement(handshake.payload.notary)
// And add a request for a time-window: it may be that none of the contracts need this!
// We set the transaction's time-window: it may be that none of the contracts need this!
// But it can't hurt to have one.
ptx.addTimeWindow(serviceHub.clock.instant(), 30.seconds)
ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds)
return Pair(ptx, arrayListOf(deal.participants.single { it == serviceHub.myInfo.legalIdentity as AbstractParty }.owningKey))
}
}

View File

@ -195,10 +195,10 @@ object TwoPartyTradeFlow {
tx.addOutputState(state, tradeRequest.assetForSale.state.notary)
tx.addCommand(command, tradeRequest.assetForSale.state.data.owner.owningKey)
// And add a request for a time-window: it may be that none of the contracts need this!
// We set the transaction's time-window: it may be that none of the contracts need this!
// But it can't hurt to have one.
val currentTime = serviceHub.clock.instant()
tx.addTimeWindow(currentTime, 30.seconds)
tx.setTimeWindow(currentTime, 30.seconds)
return Pair(tx, cashSigningPubKeys)
}
// DOCEND 1

View File

@ -260,7 +260,7 @@ class CommercialPaperTestsGeneric {
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
val issuance = bigCorpServices.myInfo.legalIdentity.ref(1)
val issueBuilder = CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY)
issueBuilder.addTimeWindow(TEST_TX_TIME, 30.seconds)
issueBuilder.setTimeWindow(TEST_TX_TIME, 30.seconds)
val issuePtx = bigCorpServices.signInitialTransaction(issueBuilder)
val issueTx = notaryServices.addSignature(issuePtx)
@ -289,7 +289,7 @@ class CommercialPaperTestsGeneric {
databaseBigCorp.transaction {
fun makeRedeemTX(time: Instant): Pair<SignedTransaction, UUID> {
val builder = TransactionType.General.Builder(DUMMY_NOTARY)
builder.addTimeWindow(time, 30.seconds)
builder.setTimeWindow(time, 30.seconds)
CommercialPaper().generateRedeem(builder, moveTX.tx.outRef(1), bigCorpVaultService)
val ptx = aliceServices.signInitialTransaction(builder)
val ptx2 = bigCorpServices.addSignature(ptx)

View File

@ -172,7 +172,7 @@ fun issueMultiPartyState(nodeA: AbstractNode, nodeB: AbstractNode, notaryNode: A
fun issueInvalidState(node: AbstractNode, notary: Party): StateAndRef<*> {
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.legalIdentity.ref(0))
tx.addTimeWindow(Instant.now(), 30.seconds)
tx.setTimeWindow(Instant.now(), 30.seconds)
val stx = node.services.signInitialTransaction(tx)
node.services.recordTransactions(stx)
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))

View File

@ -43,7 +43,7 @@ class NotaryServiceTests {
val stx = run {
val inputState = issueState(clientNode)
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
tx.addTimeWindow(Instant.now(), 30.seconds)
tx.setTimeWindow(Instant.now(), 30.seconds)
clientNode.services.signInitialTransaction(tx)
}
@ -68,7 +68,7 @@ class NotaryServiceTests {
val stx = run {
val inputState = issueState(clientNode)
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
tx.addTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
tx.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
clientNode.services.signInitialTransaction(tx)
}

View File

@ -1241,7 +1241,7 @@ class VaultQueryTests {
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
val commercialPaper =
CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY).apply {
addTimeWindow(TEST_TX_TIME, 30.seconds)
setTimeWindow(TEST_TX_TIME, 30.seconds)
signWith(MEGA_CORP_KEY)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
@ -1251,7 +1251,7 @@ class VaultQueryTests {
val faceValue2 = 10000.POUNDS `issued by` DUMMY_CASH_ISSUER
val commercialPaper2 =
CommercialPaper().generateIssue(issuance, faceValue2, TEST_TX_TIME + 30.days, DUMMY_NOTARY).apply {
addTimeWindow(TEST_TX_TIME, 30.seconds)
setTimeWindow(TEST_TX_TIME, 30.seconds)
signWith(MEGA_CORP_KEY)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
@ -1278,7 +1278,7 @@ class VaultQueryTests {
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
val commercialPaper =
CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY).apply {
addTimeWindow(TEST_TX_TIME, 30.seconds)
setTimeWindow(TEST_TX_TIME, 30.seconds)
signWith(MEGA_CORP_KEY)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
@ -1288,7 +1288,7 @@ class VaultQueryTests {
val faceValue2 = 5000.POUNDS `issued by` DUMMY_CASH_ISSUER
val commercialPaper2 =
CommercialPaper().generateIssue(issuance, faceValue2, TEST_TX_TIME + 30.days, DUMMY_NOTARY).apply {
addTimeWindow(TEST_TX_TIME, 30.seconds)
setTimeWindow(TEST_TX_TIME, 30.seconds)
signWith(MEGA_CORP_KEY)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()

View File

@ -72,9 +72,9 @@ object FixingFlow {
override fun beforeSigning(fix: Fix) {
newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload.ref), fix)
// And add a request for a time-window: it may be that none of the contracts need this!
// We set the transaction's time-window: it may be that none of the contracts need this!
// But it can't hurt to have one.
ptx.addTimeWindow(serviceHub.clock.instant(), 30.seconds)
ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds)
}
@Suspendable

View File

@ -227,7 +227,7 @@ class IRSTests {
calculation = dummyIRS.calculation,
common = dummyIRS.common,
notary = DUMMY_NOTARY).apply {
addTimeWindow(TEST_TX_TIME, 30.seconds)
setTimeWindow(TEST_TX_TIME, 30.seconds)
}
val ptx1 = megaCorpServices.signInitialTransaction(gtx)
val ptx2 = miniCorpServices.addSignature(ptx1)
@ -311,7 +311,7 @@ class IRSTests {
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
val fixing = Fix(nextFix, "0.052".percent.value)
InterestRateSwap().generateFix(tx, previousTXN.tx.outRef(0), fixing)
tx.addTimeWindow(TEST_TX_TIME, 30.seconds)
tx.setTimeWindow(TEST_TX_TIME, 30.seconds)
val ptx1 = megaCorpServices.signInitialTransaction(tx)
val ptx2 = miniCorpServices.addSignature(ptx1)
notaryServices.addSignature(ptx2)

View File

@ -20,7 +20,7 @@ object StateRevisionFlow {
override fun assembleTx(): AbstractStateReplacementFlow.UpgradeTx {
val state = originalState.state.data
val tx = state.generateRevision(originalState.state.notary, originalState, modification)
tx.addTimeWindow(serviceHub.clock.instant(), 30.seconds)
tx.setTimeWindow(serviceHub.clock.instant(), 30.seconds)
val stx = serviceHub.signInitialTransaction(tx)
val participantKeys = state.participants.map { it.owningKey }

View File

@ -82,7 +82,7 @@ class SellerFlow(val otherParty: Party,
tx.addAttachment(serviceHub.attachments.openAttachment(PROSPECTUS_HASH)!!.id)
// Requesting a time-window to be set, all CP must have a validation window.
tx.addTimeWindow(Instant.now(), 30.seconds)
tx.setTimeWindow(Instant.now(), 30.seconds)
// Sign it as ourselves.
val stx = serviceHub.signInitialTransaction(tx)

View File

@ -145,7 +145,7 @@ data class TestTransactionDSLInterpreter private constructor(
}
override fun timeWindow(data: TimeWindow) {
transactionBuilder.addTimeWindow(data)
transactionBuilder.timeWindow = data
}
override fun tweak(

View File

@ -52,7 +52,7 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup {
fun _command(signers: List<PublicKey>, commandData: CommandData)
/**
* Adds a time-window to the transaction.
* Sets the time-window of the transaction.
* @param data the [TimeWindow] (validation window).
*/
fun timeWindow(data: TimeWindow)
@ -116,7 +116,7 @@ class TransactionDSL<out T : TransactionDSLInterpreter>(val interpreter: T) : Tr
fun command(signer: PublicKey, commandData: CommandData) = _command(listOf(signer), commandData)
/**
* Adds a [TimeWindow] command to the transaction.
* Sets the [TimeWindow] of the transaction.
* @param time The [Instant] of the [TimeWindow].
* @param tolerance The tolerance of the [TimeWindow].
*/