mirror of
https://github.com/corda/corda.git
synced 2025-01-10 23:12:38 +00:00
CORDA-3009 - Migrate identity service to use to string short (#5217)
* migrate PersistentIdentityService to use key.toShortString() update definition of PublicKeyToExternalId mapping to allow fast lookup by externalId/publicKey * fix misspelled table name * add test of migration script * add design document for proposal to move IdentityService to using the correct PK.toStringShort() method for hashing a publickey * add enterprise testing considerations to design * address review comments * fix compilation errors * modify PublicKeyToOwningIdentityCache to use toStringShort() as it's lookup key * address syzmon's code review comments
This commit is contained in:
parent
7f89577f83
commit
e35c0c1df7
@ -153,5 +153,4 @@ class CordaRPCClientReconnectionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,8 +6,8 @@ import net.corda.testing.core.SerializationEnvironmentRule;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static net.corda.core.serialization.internal.CheckpointSerializationAPIKt.checkpointSerialize;
|
|
||||||
import static net.corda.core.serialization.SerializationAPIKt.serialize;
|
import static net.corda.core.serialization.SerializationAPIKt.serialize;
|
||||||
|
import static net.corda.core.serialization.internal.CheckpointSerializationAPIKt.checkpointSerialize;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -377,6 +377,7 @@ class ConstraintsPropagationTests {
|
|||||||
SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
|
SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
|
||||||
recordTransactions(SignedTransaction(wireTransaction, sigs))
|
recordTransactions(SignedTransaction(wireTransaction, sigs))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Input state contract version may be incompatible with lower version`() {
|
fun `Input state contract version may be incompatible with lower version`() {
|
||||||
ledgerServices.ledger(DUMMY_NOTARY) {
|
ledgerServices.ledger(DUMMY_NOTARY) {
|
||||||
|
@ -31,7 +31,6 @@ class X509NameConstraintsTest {
|
|||||||
private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair<X509KeyStore, X509KeyStore> {
|
private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair<X509KeyStore, X509KeyStore> {
|
||||||
val (rootCa, intermediateCa) = createDevIntermediateCaCertPath()
|
val (rootCa, intermediateCa) = createDevIntermediateCaCertPath()
|
||||||
|
|
||||||
|
|
||||||
val trustStore = X509KeyStore(storePassword).apply {
|
val trustStore = X509KeyStore(storePassword).apply {
|
||||||
setCertificate(X509Utilities.CORDA_ROOT_CA, rootCa.certificate)
|
setCertificate(X509Utilities.CORDA_ROOT_CA, rootCa.certificate)
|
||||||
}
|
}
|
||||||
|
@ -156,6 +156,7 @@ class AttachmentTests : WithMockNet {
|
|||||||
|
|
||||||
//region Matchers
|
//region Matchers
|
||||||
private fun noAttachments() = has(FetchDataFlow.Result<Attachment>::fromDisk, isEmpty)
|
private fun noAttachments() = has(FetchDataFlow.Result<Attachment>::fromDisk, isEmpty)
|
||||||
|
|
||||||
private fun soleAttachment(attachment: Attachment) = has(FetchDataFlow.Result<Attachment>::fromDisk,
|
private fun soleAttachment(attachment: Attachment) = has(FetchDataFlow.Result<Attachment>::fromDisk,
|
||||||
hasSize(equalTo(1)) and
|
hasSize(equalTo(1)) and
|
||||||
hasElement(attachment))
|
hasElement(attachment))
|
||||||
|
@ -5,12 +5,8 @@ import com.natpryce.hamkrest.assertion.assertThat
|
|||||||
import net.corda.core.contracts.Command
|
import net.corda.core.contracts.Command
|
||||||
import net.corda.core.contracts.StateAndContract
|
import net.corda.core.contracts.StateAndContract
|
||||||
import net.corda.core.contracts.requireThat
|
import net.corda.core.contracts.requireThat
|
||||||
import net.corda.core.identity.*
|
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.*
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.identity.excludeHostNode
|
|
||||||
import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
@ -106,7 +102,8 @@ class CollectSignaturesFlowTests : WithContracts {
|
|||||||
val keysToLookup = listOf(bConfidentialIdentity1.owningKey, bConfidentialIdentity2.owningKey, cConfidentialIdentity1.owningKey)
|
val keysToLookup = listOf(bConfidentialIdentity1.owningKey, bConfidentialIdentity2.owningKey, cConfidentialIdentity1.owningKey)
|
||||||
val keysToKeepAnonymous = listOf(cConfidentialIdentity2.owningKey)
|
val keysToKeepAnonymous = listOf(cConfidentialIdentity2.owningKey)
|
||||||
|
|
||||||
val future = aliceNode.startFlow(MixAndMatchAnonymousSessionTestFlow(owners, keysToLookup.toSet(), keysToKeepAnonymous.toSet())).resultFuture
|
val future = aliceNode.startFlow(MixAndMatchAnonymousSessionTestFlow(owners, keysToLookup.toSet(), keysToKeepAnonymous.toSet()))
|
||||||
|
.resultFuture
|
||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
val stx = future.get()
|
val stx = future.get()
|
||||||
val missingSigners = stx.getMissingSigners()
|
val missingSigners = stx.getMissingSigners()
|
||||||
@ -214,7 +211,6 @@ class AnonymousSessionTestFlow(private val cis: List<PartyAndCertificate>) : Flo
|
|||||||
.addOutputState(state)
|
.addOutputState(state)
|
||||||
.addCommand(create, cis.map { it.owningKey })
|
.addCommand(create, cis.map { it.owningKey })
|
||||||
|
|
||||||
|
|
||||||
val ourKey = cis.single { it.name == ourIdentity.name }.owningKey
|
val ourKey = cis.single { it.name == ourIdentity.name }.owningKey
|
||||||
val signedByUsTx = serviceHub.signInitialTransaction(txBuilder, ourKey)
|
val signedByUsTx = serviceHub.signInitialTransaction(txBuilder, ourKey)
|
||||||
val sessionsToCollectFrom = cis.filter { it.name != ourIdentity.name }.map { initiateFlow(AnonymousParty(it.owningKey)) }
|
val sessionsToCollectFrom = cis.filter { it.name != ourIdentity.name }.map { initiateFlow(AnonymousParty(it.owningKey)) }
|
||||||
@ -253,7 +249,6 @@ class MixAndMatchAnonymousSessionTestFlow(private val cis: List<PartyAndCertific
|
|||||||
.addOutputState(state)
|
.addOutputState(state)
|
||||||
.addCommand(create, cis.map { it.owningKey })
|
.addCommand(create, cis.map { it.owningKey })
|
||||||
|
|
||||||
|
|
||||||
val ourKey = cis.single { it.name == ourIdentity.name }.owningKey
|
val ourKey = cis.single { it.name == ourIdentity.name }.owningKey
|
||||||
val signedByUsTx = serviceHub.signInitialTransaction(txBuilder, ourKey)
|
val signedByUsTx = serviceHub.signInitialTransaction(txBuilder, ourKey)
|
||||||
|
|
||||||
|
@ -3,12 +3,12 @@ package net.corda.coretests.flows
|
|||||||
import com.natpryce.hamkrest.and
|
import com.natpryce.hamkrest.and
|
||||||
import com.natpryce.hamkrest.assertion.assertThat
|
import com.natpryce.hamkrest.assertion.assertThat
|
||||||
import net.corda.core.flows.FinalityFlow
|
import net.corda.core.flows.FinalityFlow
|
||||||
import net.corda.coretests.flows.WithFinality.FinalityInvoker
|
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.cordapp.CordappResolver
|
import net.corda.core.internal.cordapp.CordappResolver
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.coretests.flows.WithFinality.FinalityInvoker
|
||||||
import net.corda.finance.POUNDS
|
import net.corda.finance.POUNDS
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
import net.corda.finance.issuedBy
|
import net.corda.finance.issuedBy
|
||||||
|
@ -9,9 +9,9 @@ import net.corda.core.utilities.OpaqueBytes
|
|||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.finance.GBP
|
import net.corda.finance.GBP
|
||||||
import net.corda.finance.POUNDS
|
import net.corda.finance.POUNDS
|
||||||
import net.corda.finance.workflows.getCashBalance
|
|
||||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||||
import net.corda.finance.flows.CashPaymentReceiverFlow
|
import net.corda.finance.flows.CashPaymentReceiverFlow
|
||||||
|
import net.corda.finance.workflows.getCashBalance
|
||||||
import net.corda.node.services.statemachine.StaffedFlowHospital.*
|
import net.corda.node.services.statemachine.StaffedFlowHospital.*
|
||||||
import net.corda.node.services.statemachine.StaffedFlowHospital.MedicalRecord.Flow
|
import net.corda.node.services.statemachine.StaffedFlowHospital.MedicalRecord.Flow
|
||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
|
@ -59,7 +59,8 @@ class ReferencedStatesFlowTests {
|
|||||||
|
|
||||||
// 4. Try to use the old reference state. This will throw a NotaryException.
|
// 4. Try to use the old reference state. This will throw a NotaryException.
|
||||||
val nodeOneIdentity = nodes[1].info.legalIdentities.first()
|
val nodeOneIdentity = nodes[1].info.legalIdentities.first()
|
||||||
val useRefTx = nodes[1].services.startFlow(WithReferencedStatesFlow { UseRefState(nodeOneIdentity, newRefState.state.data.linearId) }).resultFuture
|
val useRefTx = nodes[1].services.startFlow(WithReferencedStatesFlow { UseRefState(nodeOneIdentity, newRefState.state.data.linearId) })
|
||||||
|
.resultFuture
|
||||||
|
|
||||||
// 5. Share the update reference state.
|
// 5. Share the update reference state.
|
||||||
nodes[0].services.startFlow(Initiator(updatedRefState)).resultFuture.getOrThrow()
|
nodes[0].services.startFlow(Initiator(updatedRefState)).resultFuture.getOrThrow()
|
||||||
@ -75,7 +76,8 @@ class ReferencedStatesFlowTests {
|
|||||||
val newRefTx = nodes[0].services.startFlow(CreateRefState()).resultFuture.getOrThrow()
|
val newRefTx = nodes[0].services.startFlow(CreateRefState()).resultFuture.getOrThrow()
|
||||||
val newRefState = newRefTx.tx.outRefsOfType<RefState.State>().single()
|
val newRefState = newRefTx.tx.outRefsOfType<RefState.State>().single()
|
||||||
// 2. Use the "newRefState" a transaction involving another party (nodes[1]) which creates a new state. They should store the new state and the reference state.
|
// 2. Use the "newRefState" a transaction involving another party (nodes[1]) which creates a new state. They should store the new state and the reference state.
|
||||||
val newTx = nodes[0].services.startFlow(UseRefState(nodes[1].info.legalIdentities.first(), newRefState.state.data.linearId)).resultFuture.getOrThrow()
|
val newTx = nodes[0].services.startFlow(UseRefState(nodes[1].info.legalIdentities.first(), newRefState.state.data.linearId))
|
||||||
|
.resultFuture.getOrThrow()
|
||||||
// Wait until node 1 stores the new tx.
|
// Wait until node 1 stores the new tx.
|
||||||
nodes[1].services.validatedTransactions.trackTransaction(newTx.id).getOrThrow()
|
nodes[1].services.validatedTransactions.trackTransaction(newTx.id).getOrThrow()
|
||||||
// Check that nodes[1] has finished recording the transaction (and updating the vault.. hopefully!).
|
// Check that nodes[1] has finished recording the transaction (and updating the vault.. hopefully!).
|
||||||
@ -106,7 +108,8 @@ class ReferencedStatesFlowTests {
|
|||||||
val newRefTx = nodes[0].services.startFlow(CreateRefState()).resultFuture.getOrThrow()
|
val newRefTx = nodes[0].services.startFlow(CreateRefState()).resultFuture.getOrThrow()
|
||||||
val newRefState = newRefTx.tx.outRefsOfType<RefState.State>().single()
|
val newRefState = newRefTx.tx.outRefsOfType<RefState.State>().single()
|
||||||
// 2. Use the "newRefState" a transaction involving another party (nodes[1]) which creates a new state. They should store the new state and the reference state.
|
// 2. Use the "newRefState" a transaction involving another party (nodes[1]) which creates a new state. They should store the new state and the reference state.
|
||||||
val newTx = nodes[0].services.startFlow(UseRefState(nodes[1].info.legalIdentities.first(), newRefState.state.data.linearId)).resultFuture.getOrThrow()
|
val newTx = nodes[0].services.startFlow(UseRefState(nodes[1].info.legalIdentities.first(), newRefState.state.data.linearId))
|
||||||
|
.resultFuture.getOrThrow()
|
||||||
// Wait until node 1 stores the new tx.
|
// Wait until node 1 stores the new tx.
|
||||||
nodes[1].services.validatedTransactions.trackTransaction(newTx.id).getOrThrow()
|
nodes[1].services.validatedTransactions.trackTransaction(newTx.id).getOrThrow()
|
||||||
// Check that nodes[1] has finished recording the transaction (and updating the vault.. hopefully!).
|
// Check that nodes[1] has finished recording the transaction (and updating the vault.. hopefully!).
|
||||||
|
@ -430,6 +430,7 @@ class ResolveTransactionsFlowTest {
|
|||||||
subFlow(resolveTransactionsFlow)
|
subFlow(resolveTransactionsFlow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@InitiatedBy(TestFlow::class)
|
@InitiatedBy(TestFlow::class)
|
||||||
class TestResponseFlow(private val otherSideSession: FlowSession) : FlowLogic<Void?>() {
|
class TestResponseFlow(private val otherSideSession: FlowSession) : FlowLogic<Void?>() {
|
||||||
@ -447,6 +448,7 @@ class ResolveTransactionsFlowTest {
|
|||||||
subFlow(DataVendingFlow(session, toVend))
|
subFlow(DataVendingFlow(session, toVend))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@InitiatedBy(TestNoRightsVendingFlow::class)
|
@InitiatedBy(TestNoRightsVendingFlow::class)
|
||||||
private open class TestResponseResolveNoRightsFlow(val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
private open class TestResponseResolveNoRightsFlow(val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
||||||
@ -454,7 +456,8 @@ class ResolveTransactionsFlowTest {
|
|||||||
override fun call() {
|
override fun call() {
|
||||||
val noRightsTx = otherSideSession.receive<SignedTransaction>().unwrap { it }
|
val noRightsTx = otherSideSession.receive<SignedTransaction>().unwrap { it }
|
||||||
otherSideSession.receive<Any>().unwrap { it }
|
otherSideSession.receive<Any>().unwrap { it }
|
||||||
otherSideSession.sendAndReceive<Any>(FetchDataFlow.Request.Data(NonEmptySet.of(noRightsTx.inputs.first().txhash), FetchDataFlow.DataType.TRANSACTION)).unwrap { it }
|
otherSideSession.sendAndReceive<Any>(FetchDataFlow.Request.Data(NonEmptySet.of(noRightsTx.inputs.first().txhash), FetchDataFlow.DataType.TRANSACTION))
|
||||||
|
.unwrap { it }
|
||||||
otherSideSession.send(FetchDataFlow.Request.End)
|
otherSideSession.send(FetchDataFlow.Request.End)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,6 +471,7 @@ class ResolveTransactionsFlowTest {
|
|||||||
subFlow(DataVendingFlow(session, tx))
|
subFlow(DataVendingFlow(session, tx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@InitiatedBy(TestResolveTwiceVendingFlow::class)
|
@InitiatedBy(TestResolveTwiceVendingFlow::class)
|
||||||
private open class TestResponseResolveTwiceFlow(val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
private open class TestResponseResolveTwiceFlow(val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
||||||
@ -475,8 +479,10 @@ class ResolveTransactionsFlowTest {
|
|||||||
override fun call() {
|
override fun call() {
|
||||||
val tx = otherSideSession.receive<SignedTransaction>().unwrap { it }
|
val tx = otherSideSession.receive<SignedTransaction>().unwrap { it }
|
||||||
val parent1 = tx.inputs.first().txhash
|
val parent1 = tx.inputs.first().txhash
|
||||||
otherSideSession.sendAndReceive<Any>(FetchDataFlow.Request.Data(NonEmptySet.of(parent1), FetchDataFlow.DataType.TRANSACTION)).unwrap { it }
|
otherSideSession.sendAndReceive<Any>(FetchDataFlow.Request.Data(NonEmptySet.of(parent1), FetchDataFlow.DataType.TRANSACTION))
|
||||||
otherSideSession.sendAndReceive<Any>(FetchDataFlow.Request.Data(NonEmptySet.of(parent1), FetchDataFlow.DataType.TRANSACTION)).unwrap { it }
|
.unwrap { it }
|
||||||
|
otherSideSession.sendAndReceive<Any>(FetchDataFlow.Request.Data(NonEmptySet.of(parent1), FetchDataFlow.DataType.TRANSACTION))
|
||||||
|
.unwrap { it }
|
||||||
otherSideSession.send(FetchDataFlow.Request.End)
|
otherSideSession.send(FetchDataFlow.Request.End)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import org.junit.Test
|
|||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
|
|
||||||
class VaultUpdateTests {
|
class VaultUpdateTests {
|
||||||
private companion object {
|
private companion object {
|
||||||
const val DUMMY_PROGRAM_ID = "net.corda.coretests.node.VaultUpdateTests\$DummyContract"
|
const val DUMMY_PROGRAM_ID = "net.corda.coretests.node.VaultUpdateTests\$DummyContract"
|
||||||
|
@ -3,7 +3,9 @@ package net.corda.coretests.serialization
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.contracts.Attachment
|
import net.corda.core.contracts.Attachment
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.FlowSession
|
||||||
|
import net.corda.core.flows.InitiatingFlow
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.FetchAttachmentsFlow
|
import net.corda.core.internal.FetchAttachmentsFlow
|
||||||
import net.corda.core.internal.FetchDataFlow
|
import net.corda.core.internal.FetchDataFlow
|
||||||
|
@ -2,13 +2,17 @@ package net.corda.coretests.serialization
|
|||||||
|
|
||||||
import com.nhaarman.mockito_kotlin.mock
|
import com.nhaarman.mockito_kotlin.mock
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.Crypto
|
||||||
|
import net.corda.core.crypto.SignatureMetadata
|
||||||
|
import net.corda.core.crypto.TransactionSignature
|
||||||
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.NotaryInfo
|
import net.corda.core.node.NotaryInfo
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.transactions.*
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.finance.POUNDS
|
import net.corda.finance.POUNDS
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
|
@ -3,10 +3,10 @@ package net.corda.coretests.transactions
|
|||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.contracts.ComponentGroupEnum.*
|
import net.corda.core.contracts.ComponentGroupEnum.*
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.*
|
||||||
import net.corda.core.internal.createComponentGroups
|
|
||||||
import net.corda.core.internal.accessAvailableComponentHashes
|
import net.corda.core.internal.accessAvailableComponentHashes
|
||||||
import net.corda.core.internal.accessGroupHashes
|
import net.corda.core.internal.accessGroupHashes
|
||||||
import net.corda.core.internal.accessGroupMerkleRoots
|
import net.corda.core.internal.accessGroupMerkleRoots
|
||||||
|
import net.corda.core.internal.createComponentGroups
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.transactions.*
|
import net.corda.core.transactions.*
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
@ -17,7 +17,6 @@ import org.junit.Rule
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import kotlin.reflect.KVisibility
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class CompatibleTransactionTests {
|
class CompatibleTransactionTests {
|
||||||
@ -420,7 +419,6 @@ class CompatibleTransactionTests {
|
|||||||
// Required to call the private constructor.
|
// Required to call the private constructor.
|
||||||
val ftxConstructor = FilteredTransaction::class.constructors.first()
|
val ftxConstructor = FilteredTransaction::class.constructors.first()
|
||||||
|
|
||||||
|
|
||||||
// 1st and 3rd commands require a signature from KEY_1.
|
// 1st and 3rd commands require a signature from KEY_1.
|
||||||
val twoCommandsforKey1 = listOf(dummyCommand(DUMMY_KEY_1.public, DUMMY_KEY_2.public), dummyCommand(DUMMY_KEY_2.public), dummyCommand(DUMMY_KEY_1.public))
|
val twoCommandsforKey1 = listOf(dummyCommand(DUMMY_KEY_1.public, DUMMY_KEY_2.public), dummyCommand(DUMMY_KEY_2.public), dummyCommand(DUMMY_KEY_1.public))
|
||||||
val componentGroups = listOf(
|
val componentGroups = listOf(
|
||||||
|
@ -22,7 +22,7 @@ import net.corda.testing.core.SerializationEnvironmentRule
|
|||||||
import net.corda.testing.core.TestIdentity
|
import net.corda.testing.core.TestIdentity
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import net.corda.testing.node.ledger
|
import net.corda.testing.node.ledger
|
||||||
import org.assertj.core.api.Assertions.*
|
import org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@ package net.corda.coretests.utilities
|
|||||||
|
|
||||||
import com.esotericsoftware.kryo.KryoException
|
import com.esotericsoftware.kryo.KryoException
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.ClassWhitelist
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.internal.checkpointDeserialize
|
import net.corda.core.serialization.internal.checkpointDeserialize
|
||||||
import net.corda.core.serialization.internal.checkpointSerialize
|
import net.corda.core.serialization.internal.checkpointSerialize
|
||||||
import net.corda.core.utilities.transient
|
import net.corda.core.utilities.transient
|
||||||
|
@ -2,7 +2,6 @@ package net.corda.core.internal
|
|||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
import net.corda.core.DeleteForDJVM
|
||||||
import net.corda.core.contracts.Attachment
|
import net.corda.core.contracts.Attachment
|
||||||
import net.corda.core.contracts.ContractAttachment
|
|
||||||
import net.corda.core.contracts.ContractClassName
|
import net.corda.core.contracts.ContractClassName
|
||||||
import net.corda.core.flows.DataVendingFlow
|
import net.corda.core.flows.DataVendingFlow
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
|
@ -4,7 +4,10 @@ import co.paralleluniverse.strands.Strand
|
|||||||
import net.corda.core.CordaInternal
|
import net.corda.core.CordaInternal
|
||||||
import net.corda.core.DeleteForDJVM
|
import net.corda.core.DeleteForDJVM
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.CompositeKey
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.crypto.SignableData
|
||||||
|
import net.corda.core.crypto.SignatureMetadata
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package net.corda.core.internal
|
package net.corda.core.internal
|
||||||
|
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.MerkleTree
|
|
||||||
import net.corda.core.crypto.PartialMerkleTree
|
import net.corda.core.crypto.PartialMerkleTree
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.SerializedStateAndRef
|
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.transactions.ComponentGroup
|
import net.corda.core.transactions.ComponentGroup
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
@ -16,6 +14,7 @@ import net.corda.core.transactions.WireTransaction
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
fun WireTransaction.accessGroupHashes() = this.groupHashes
|
fun WireTransaction.accessGroupHashes() = this.groupHashes
|
||||||
|
|
||||||
fun WireTransaction.accessGroupMerkleRoots() = this.groupsMerkleRoots
|
fun WireTransaction.accessGroupMerkleRoots() = this.groupsMerkleRoots
|
||||||
fun WireTransaction.accessAvailableComponentHashes() = this.availableComponentHashes
|
fun WireTransaction.accessAvailableComponentHashes() = this.availableComponentHashes
|
||||||
|
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
# Design doc template
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
We wish to move the `PersistentIdentityService` away from using `PublicKey.hash.toHexString()` to using the correct method
|
||||||
|
`PublicKey.toStringShort()`
|
||||||
|
|
||||||
|
This requires modifying the `PersistentIdentityService` and an accompanying Database Migration.
|
||||||
|
|
||||||
|
**It is important to note that the underlying hash function will be sha256 both in the old and new implementations, the only difference is the stored representation.**
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
In Corda4 we introduced an ability to map a given `PublicKey` to a UUID. Internally this builds a database table which maintains a mapping
|
||||||
|
between `H(PublicKey)` -> UUID. Where `H()` is `PublicKey.toStringShort()`.
|
||||||
|
|
||||||
|
There is a reasonable requirement that for a given `UUID` you would want to find all the keys that are associated with that UUID.
|
||||||
|
To do this, we would need to join the `PublicKeyHashToExternalId` table with the `PersistentIdentity` table.
|
||||||
|
|
||||||
|
This is currently impossible due to the fact that the two tables use different hashes.
|
||||||
|
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
* Migrate `PersistentIdentityService` to use `PublicKey.toStringShort()`
|
||||||
|
* Migrate the existing stored data
|
||||||
|
|
||||||
|
## Timeline
|
||||||
|
|
||||||
|
* This would be required for usage of Accounts. Therefore, it would need to be included in any release that is intended for clients using Accounts.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* It must be possible to join the `PublicKeyHashToExternalId` table with the `PersistentIdentity` table.
|
||||||
|
* Existing Identities must be safely migrated to using the new hashing approach.
|
||||||
|
|
||||||
|
## Design Decisions
|
||||||
|
|
||||||
|
* We will use Liquibase to perform the migration
|
||||||
|
|
||||||
|
## Design
|
||||||
|
|
||||||
|
The intention is to remove the use of `SecureHash` as an intermediary step in hashing a `PublicKey` and instead directly invoke `toStringShort()`.
|
||||||
|
This will ensure that for the same PK, all the tables within the node share a joinable column.
|
||||||
|
|
||||||
|
Luckily within the `PersistentIdentity` table, we store the full `PartyAndCertificate` which allows us to load the previously stored record,
|
||||||
|
and obtain the correct hash. We can then use the same `PartyAndCertificate` to calculate the originally stored value,
|
||||||
|
and perform a simple `UPDATE RECORD SET RECORD.PK_HASH = <new_value> WHERE RECORD.PK_HASH = <old_value>` to safely migrate the data.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
It is possible to write a simple Unit Test to insert records into the table using the old hashing mechanism, execute the migration.
|
||||||
|
and then check that the expected value is present within the updated rows. This will give a level of confidence that the migration is safe.
|
||||||
|
|
||||||
|
For more extensive testing, we propose to start a node using an unfixed C4 version, insert some Identities (both well known and confidential)
|
||||||
|
shutdown the node, place a fixed version and then check that the identities are resolvable and present in the database with the correct form of hash.
|
||||||
|
|
||||||
|
For enterprise, the testing performed with H2 (start, shutdown, migrate, restart) must be performed for all the supported database engines
|
||||||
|
both using the DbMigrationTool and by allowing the node to migrate itself.
|
||||||
|
|
||||||
|
|
||||||
|
To see a reference implementation of this design check out: https://github.com/corda/corda/pull/5217/files
|
@ -5,14 +5,13 @@ import com.typesafe.config.ConfigFactory
|
|||||||
import com.typesafe.config.ConfigParseOptions
|
import com.typesafe.config.ConfigParseOptions
|
||||||
import net.corda.cliutils.CordaCliWrapper
|
import net.corda.cliutils.CordaCliWrapper
|
||||||
import net.corda.cliutils.start
|
import net.corda.cliutils.start
|
||||||
import net.corda.core.crypto.Crypto
|
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.copyTo
|
||||||
|
import net.corda.core.internal.readObject
|
||||||
|
import net.corda.core.internal.signWithCertPath
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.node.NotaryInfo
|
import net.corda.core.node.NotaryInfo
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
import net.corda.core.serialization.SerializedBytes
|
|
||||||
import net.corda.core.serialization.deserialize
|
|
||||||
import net.corda.core.serialization.internal.SerializationEnvironment
|
import net.corda.core.serialization.internal.SerializationEnvironment
|
||||||
import net.corda.core.serialization.internal.nodeSerializationEnv
|
import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
@ -20,9 +19,12 @@ import net.corda.nodeapi.internal.SignedNodeInfo
|
|||||||
import net.corda.nodeapi.internal.createDevNetworkMapCa
|
import net.corda.nodeapi.internal.createDevNetworkMapCa
|
||||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||||
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
||||||
import net.corda.serialization.internal.*
|
import net.corda.serialization.internal.AMQP_P2P_CONTEXT
|
||||||
import net.corda.serialization.internal.amqp.*
|
import net.corda.serialization.internal.CordaSerializationMagic
|
||||||
import picocli.CommandLine.*
|
import net.corda.serialization.internal.SerializationFactoryImpl
|
||||||
|
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||||
|
import net.corda.serialization.internal.amqp.amqpMagic
|
||||||
|
import picocli.CommandLine.Option
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.StandardCopyOption
|
import java.nio.file.StandardCopyOption
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package net.corda.nodeapi.exceptions
|
package net.corda.nodeapi.exceptions
|
||||||
|
|
||||||
|
import net.corda.core.ClientRelevantError
|
||||||
import net.corda.core.CordaRuntimeException
|
import net.corda.core.CordaRuntimeException
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.ClientRelevantError
|
|
||||||
import net.corda.core.flows.IdentifiableException
|
import net.corda.core.flows.IdentifiableException
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.nodeapi.internal.config
|
|||||||
import net.corda.core.crypto.internal.AliasPrivateKey
|
import net.corda.core.crypto.internal.AliasPrivateKey
|
||||||
import net.corda.core.internal.outputStream
|
import net.corda.core.internal.outputStream
|
||||||
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
|
||||||
import net.corda.nodeapi.internal.crypto.addOrReplaceCertificate
|
import net.corda.nodeapi.internal.crypto.addOrReplaceCertificate
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
@ -3,15 +3,10 @@
|
|||||||
package net.corda.nodeapi.internal.crypto
|
package net.corda.nodeapi.internal.crypto
|
||||||
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.exists
|
|
||||||
import net.corda.core.internal.read
|
|
||||||
import net.corda.core.internal.write
|
|
||||||
import net.corda.core.internal.safeSymbolicRead
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Files
|
|
||||||
import java.security.*
|
import java.security.*
|
||||||
import java.security.cert.Certificate
|
import java.security.cert.Certificate
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
@ -2,7 +2,6 @@ package net.corda.nodeapi.internal.network
|
|||||||
|
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.internal.NODE_INFO_DIRECTORY
|
|
||||||
import net.corda.core.utilities.debug
|
import net.corda.core.utilities.debug
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Scheduler
|
import rx.Scheduler
|
||||||
|
@ -3,18 +3,13 @@ package net.corda.node.logging
|
|||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.InitiatingFlow
|
import net.corda.core.flows.InitiatingFlow
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.messaging.FlowHandle
|
import net.corda.core.messaging.FlowHandle
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.contextLogger
|
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.loggerFor
|
|
||||||
import net.corda.testing.driver.DriverParameters
|
import net.corda.testing.driver.DriverParameters
|
||||||
import net.corda.testing.driver.NodeHandle
|
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class ErrorCodeLoggingTests {
|
class ErrorCodeLoggingTests {
|
||||||
@Test
|
@Test
|
||||||
|
@ -17,6 +17,7 @@ import net.corda.finance.contracts.asset.Cash
|
|||||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||||
import net.corda.finance.schemas.CashSchemaV1
|
import net.corda.finance.schemas.CashSchemaV1
|
||||||
import net.corda.node.services.Permissions
|
import net.corda.node.services.Permissions
|
||||||
|
import net.corda.node.services.rpc.RpcReconnectTests.Companion.NUMBER_OF_FLOWS_TO_RUN
|
||||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||||
import net.corda.testing.core.DUMMY_BANK_B_NAME
|
import net.corda.testing.core.DUMMY_BANK_B_NAME
|
||||||
import net.corda.testing.driver.DriverParameters
|
import net.corda.testing.driver.DriverParameters
|
||||||
|
@ -177,7 +177,8 @@ internal class CordaRPCOpsImpl(
|
|||||||
vendor = CordaVersion.vendor,
|
vendor = CordaVersion.vendor,
|
||||||
cordapps = services.cordappProvider.cordapps
|
cordapps = services.cordappProvider.cordapps
|
||||||
.filter { !it.jarPath.toString().endsWith("corda-core-${CordaVersion.releaseVersion}.jar") }
|
.filter { !it.jarPath.toString().endsWith("corda-core-${CordaVersion.releaseVersion}.jar") }
|
||||||
.map { CordappInfo(
|
.map {
|
||||||
|
CordappInfo(
|
||||||
type = when (it.info) {
|
type = when (it.info) {
|
||||||
is Cordapp.Info.Contract -> "Contract CorDapp"
|
is Cordapp.Info.Contract -> "Contract CorDapp"
|
||||||
is Cordapp.Info.Workflow -> "Workflow CorDapp"
|
is Cordapp.Info.Workflow -> "Workflow CorDapp"
|
||||||
|
@ -2,7 +2,10 @@ package net.corda.node.internal
|
|||||||
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.DigitalSignatureWithCert
|
||||||
|
import net.corda.core.internal.NamedCacheFactory
|
||||||
|
import net.corda.core.internal.NetworkParametersStorage
|
||||||
|
import net.corda.core.internal.SignedDataWithCert
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.node.NotaryInfo
|
import net.corda.core.node.NotaryInfo
|
||||||
import net.corda.core.serialization.SerializedBytes
|
import net.corda.core.serialization.SerializedBytes
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package net.corda.node.internal
|
package net.corda.node.internal
|
||||||
|
|
||||||
import io.netty.channel.unix.Errors
|
import io.netty.channel.unix.Errors
|
||||||
import net.corda.cliutils.printError
|
|
||||||
import net.corda.cliutils.CliWrapperBase
|
import net.corda.cliutils.CliWrapperBase
|
||||||
import net.corda.cliutils.CordaCliWrapper
|
import net.corda.cliutils.CordaCliWrapper
|
||||||
import net.corda.cliutils.ExitCodes
|
import net.corda.cliutils.ExitCodes
|
||||||
|
import net.corda.cliutils.printError
|
||||||
import net.corda.common.logging.CordaVersion
|
import net.corda.common.logging.CordaVersion
|
||||||
import net.corda.core.contracts.HashAttachmentConstraint
|
import net.corda.core.contracts.HashAttachmentConstraint
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
@ -12,7 +12,6 @@ import net.corda.core.internal.*
|
|||||||
import net.corda.core.internal.concurrent.thenMatch
|
import net.corda.core.internal.concurrent.thenMatch
|
||||||
import net.corda.core.internal.cordapp.CordappImpl
|
import net.corda.core.internal.cordapp.CordappImpl
|
||||||
import net.corda.core.internal.errors.AddressBindingException
|
import net.corda.core.internal.errors.AddressBindingException
|
||||||
import net.corda.core.internal.safeSymbolicRead
|
|
||||||
import net.corda.core.utilities.Try
|
import net.corda.core.utilities.Try
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
@ -39,7 +38,6 @@ import java.io.RandomAccessFile
|
|||||||
import java.lang.management.ManagementFactory
|
import java.lang.management.ManagementFactory
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.nio.channels.UnresolvedAddressException
|
import java.nio.channels.UnresolvedAddressException
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package net.corda.node.migration
|
||||||
|
|
||||||
|
import liquibase.change.custom.CustomSqlChange
|
||||||
|
import liquibase.database.Database
|
||||||
|
import liquibase.exception.ValidationErrors
|
||||||
|
import liquibase.resource.ResourceAccessor
|
||||||
|
import liquibase.statement.SqlStatement
|
||||||
|
import liquibase.statement.core.UpdateStatement
|
||||||
|
import net.corda.core.crypto.toStringShort
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
|
import net.corda.core.utilities.contextLogger
|
||||||
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
|
|
||||||
|
class PersistentIdentityMigration : CustomSqlChange {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val logger = contextLogger()
|
||||||
|
const val PUB_KEY_HASH_TO_PARTY_AND_CERT_TABLE = PersistentIdentityService.HASH_TO_IDENTITY_TABLE_NAME
|
||||||
|
const val X500_NAME_TO_PUB_KEY_HASH_TABLE = PersistentIdentityService.NAME_TO_HASH_TABLE_NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun validate(database: Database?): ValidationErrors? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getConfirmationMessage(): String? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setFileOpener(resourceAccessor: ResourceAccessor?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setUp() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateStatements(database: Database?): Array<SqlStatement> {
|
||||||
|
val dataSource = MigrationDataSource(database!!)
|
||||||
|
val connection = dataSource.connection
|
||||||
|
val statement = connection.prepareStatement("SELECT * FROM $PUB_KEY_HASH_TO_PARTY_AND_CERT_TABLE")
|
||||||
|
val resultSet = statement.executeQuery()
|
||||||
|
val generatedStatements = mutableListOf<SqlStatement>()
|
||||||
|
while (resultSet.next()) {
|
||||||
|
val oldPkHash = resultSet.getString(1)
|
||||||
|
val identityBytes = resultSet.getBytes(2)
|
||||||
|
val partyAndCertificate = PartyAndCertificate(X509CertificateFactory().delegate.generateCertPath(identityBytes.inputStream()))
|
||||||
|
generatedStatements.addAll(MigrationData(oldPkHash, partyAndCertificate).let { listOf(updateHashToIdentityRow(it, dataSource), updateNameToHashRow(it, dataSource)) })
|
||||||
|
}
|
||||||
|
return generatedStatements.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateHashToIdentityRow(migrationData: MigrationData, dataSource: MigrationDataSource): SqlStatement {
|
||||||
|
return UpdateStatement(dataSource.connection.catalog, dataSource.connection.schema, PUB_KEY_HASH_TO_PARTY_AND_CERT_TABLE)
|
||||||
|
.setWhereClause("pk_hash=?")
|
||||||
|
.addNewColumnValue("pk_hash", migrationData.newPkHash)
|
||||||
|
.addWhereParameter(migrationData.oldPkHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateNameToHashRow(migrationData: MigrationData, dataSource: MigrationDataSource): UpdateStatement {
|
||||||
|
return UpdateStatement(dataSource.connection.catalog, dataSource.connection.schema, X500_NAME_TO_PUB_KEY_HASH_TABLE)
|
||||||
|
.setWhereClause("pk_hash=? AND name=?")
|
||||||
|
.addNewColumnValue("pk_hash", migrationData.newPkHash)
|
||||||
|
.addWhereParameters(migrationData.oldPkHash, migrationData.x500.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MigrationData(val oldPkHash: String,
|
||||||
|
val partyAndCertificate: PartyAndCertificate,
|
||||||
|
val x500: CordaX500Name = partyAndCertificate.name,
|
||||||
|
val newPkHash: String = partyAndCertificate.owningKey.toStringShort())
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package net.corda.node.services.api
|
package net.corda.node.services.api
|
||||||
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.CertRole
|
import net.corda.core.internal.CertRole
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
@ -9,7 +8,6 @@ import net.corda.core.utilities.contextLogger
|
|||||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.nodeapi.internal.crypto.x509Certificates
|
import net.corda.nodeapi.internal.crypto.x509Certificates
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
import java.security.PublicKey
|
|
||||||
import java.security.cert.CertPathValidatorException
|
import java.security.cert.CertPathValidatorException
|
||||||
import java.security.cert.CertificateExpiredException
|
import java.security.cert.CertificateExpiredException
|
||||||
import java.security.cert.CertificateNotYetValidException
|
import java.security.cert.CertificateNotYetValidException
|
||||||
|
@ -3,14 +3,11 @@ package net.corda.node.services.config.schema.v1
|
|||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigException
|
import com.typesafe.config.ConfigException
|
||||||
import net.corda.common.configuration.parsing.internal.*
|
import net.corda.common.configuration.parsing.internal.*
|
||||||
|
import net.corda.common.validation.internal.Validated
|
||||||
import net.corda.common.validation.internal.Validated.Companion.invalid
|
import net.corda.common.validation.internal.Validated.Companion.invalid
|
||||||
import net.corda.common.validation.internal.Validated.Companion.valid
|
import net.corda.common.validation.internal.Validated.Companion.valid
|
||||||
import net.corda.node.services.config.JmxReporterType
|
import net.corda.node.services.config.*
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
|
||||||
import net.corda.node.services.config.NodeConfigurationImpl
|
|
||||||
import net.corda.node.services.config.NodeConfigurationImpl.Defaults
|
import net.corda.node.services.config.NodeConfigurationImpl.Defaults
|
||||||
import net.corda.node.services.config.Valid
|
|
||||||
import net.corda.node.services.config.VerifierType
|
|
||||||
import net.corda.node.services.config.schema.parsers.*
|
import net.corda.node.services.config.schema.parsers.*
|
||||||
|
|
||||||
internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfiguration>("NodeConfiguration") {
|
internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfiguration>("NodeConfiguration") {
|
||||||
@ -65,7 +62,7 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private val systemProperties by nestedObject().optional()
|
private val systemProperties by nestedObject().optional()
|
||||||
|
|
||||||
override fun parseValid(configuration: Config): Valid<NodeConfiguration> {
|
override fun parseValid(configuration: Config): Validated<NodeConfiguration, Configuration.Validation.Error> {
|
||||||
|
|
||||||
val messagingServerExternal = configuration[messagingServerExternal] ?: Defaults.messagingServerExternal(configuration[messagingServerAddress])
|
val messagingServerExternal = configuration[messagingServerExternal] ?: Defaults.messagingServerExternal(configuration[messagingServerAddress])
|
||||||
val database = configuration[database] ?: Defaults.database(configuration[devMode])
|
val database = configuration[database] ?: Defaults.database(configuration[devMode])
|
||||||
@ -127,7 +124,7 @@ internal object V1NodeConfigurationSpec : Configuration.Specification<NodeConfig
|
|||||||
else -> throw e
|
else -> throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.mapValid { conf -> Valid.withResult(conf as NodeConfiguration, conf.validate().map(::toError).toSet()) }
|
return result.mapValid { conf -> Validated.withResult(conf as NodeConfiguration, conf.validate().map(::toError).toSet()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package net.corda.node.services.identity
|
package net.corda.node.services.identity
|
||||||
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.toStringShort
|
||||||
import net.corda.core.identity.*
|
import net.corda.core.identity.*
|
||||||
import net.corda.core.internal.NamedCacheFactory
|
import net.corda.core.internal.NamedCacheFactory
|
||||||
import net.corda.core.internal.hash
|
|
||||||
import net.corda.core.internal.toSet
|
import net.corda.core.internal.toSet
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
@ -16,7 +15,7 @@ import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
|||||||
import net.corda.nodeapi.internal.crypto.x509Certificates
|
import net.corda.nodeapi.internal.crypto.x509Certificates
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
|
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
|
||||||
import org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY
|
import org.hibernate.internal.util.collections.ArrayHelper.EMPTY_BYTE_ARRAY
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.security.cert.*
|
import java.security.cert.*
|
||||||
@ -36,62 +35,69 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri
|
|||||||
companion object {
|
companion object {
|
||||||
private val log = contextLogger()
|
private val log = contextLogger()
|
||||||
|
|
||||||
fun createPKMap(cacheFactory: NamedCacheFactory): AppendOnlyPersistentMap<SecureHash, PartyAndCertificate, PersistentIdentity, String> {
|
const val HASH_TO_IDENTITY_TABLE_NAME = "${NODE_DATABASE_PREFIX}identities"
|
||||||
|
const val NAME_TO_HASH_TABLE_NAME = "${NODE_DATABASE_PREFIX}named_identities"
|
||||||
|
const val PK_HASH_COLUMN_NAME = "pk_hash"
|
||||||
|
const val IDENTITY_COLUMN_NAME = "identity_value"
|
||||||
|
const val NAME_COLUMN_NAME = "name"
|
||||||
|
|
||||||
|
fun createPKMap(cacheFactory: NamedCacheFactory): AppendOnlyPersistentMap<String, PartyAndCertificate, PersistentIdentity, String> {
|
||||||
return AppendOnlyPersistentMap(
|
return AppendOnlyPersistentMap(
|
||||||
cacheFactory = cacheFactory,
|
cacheFactory = cacheFactory,
|
||||||
name = "PersistentIdentityService_partyByKey",
|
name = "PersistentIdentityService_partyByKey",
|
||||||
toPersistentEntityKey = { it.toString() },
|
toPersistentEntityKey = { it },
|
||||||
fromPersistentEntity = {
|
fromPersistentEntity = {
|
||||||
Pair(
|
Pair(
|
||||||
SecureHash.parse(it.publicKeyHash),
|
it.publicKeyHash,
|
||||||
PartyAndCertificate(X509CertificateFactory().delegate.generateCertPath(it.identity.inputStream()))
|
PartyAndCertificate(X509CertificateFactory().delegate.generateCertPath(it.identity.inputStream()))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
toPersistentEntity = { key: SecureHash, value: PartyAndCertificate ->
|
toPersistentEntity = { key: String, value: PartyAndCertificate ->
|
||||||
PersistentIdentity(key.toString(), value.certPath.encoded)
|
PersistentIdentity(key, value.certPath.encoded)
|
||||||
},
|
},
|
||||||
persistentEntityClass = PersistentIdentity::class.java
|
persistentEntityClass = PersistentIdentity::class.java
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createX500Map(cacheFactory: NamedCacheFactory): AppendOnlyPersistentMap<CordaX500Name, SecureHash, PersistentIdentityNames, String> {
|
fun createX500Map(cacheFactory: NamedCacheFactory): AppendOnlyPersistentMap<CordaX500Name, String, PersistentIdentityNames, String> {
|
||||||
return AppendOnlyPersistentMap(
|
return AppendOnlyPersistentMap(
|
||||||
cacheFactory = cacheFactory,
|
cacheFactory = cacheFactory,
|
||||||
name = "PersistentIdentityService_partyByName",
|
name = "PersistentIdentityService_partyByName",
|
||||||
toPersistentEntityKey = { it.toString() },
|
toPersistentEntityKey = { it.toString() },
|
||||||
fromPersistentEntity = { Pair(CordaX500Name.parse(it.name), SecureHash.parse(it.publicKeyHash)) },
|
fromPersistentEntity = {
|
||||||
toPersistentEntity = { key: CordaX500Name, value: SecureHash ->
|
Pair(CordaX500Name.parse(it.name), it.publicKeyHash)
|
||||||
PersistentIdentityNames(key.toString(), value.toString())
|
},
|
||||||
|
toPersistentEntity = { key: CordaX500Name, value: String ->
|
||||||
|
PersistentIdentityNames(key.toString(), value)
|
||||||
},
|
},
|
||||||
persistentEntityClass = PersistentIdentityNames::class.java
|
persistentEntityClass = PersistentIdentityNames::class.java
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mapToKey(owningKey: PublicKey) = owningKey.hash
|
private fun mapToKey(party: PartyAndCertificate) = party.owningKey.toStringShort()
|
||||||
private fun mapToKey(party: PartyAndCertificate) = mapToKey(party.owningKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}identities")
|
@javax.persistence.Table(name = HASH_TO_IDENTITY_TABLE_NAME)
|
||||||
class PersistentIdentity(
|
class PersistentIdentity(
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
|
@Column(name = PK_HASH_COLUMN_NAME, length = MAX_HASH_HEX_SIZE, nullable = false)
|
||||||
var publicKeyHash: String = "",
|
var publicKeyHash: String = "",
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(name = "identity_value", nullable = false)
|
@Column(name = IDENTITY_COLUMN_NAME, nullable = false)
|
||||||
var identity: ByteArray = EMPTY_BYTE_ARRAY
|
var identity: ByteArray = EMPTY_BYTE_ARRAY
|
||||||
)
|
)
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}named_identities")
|
@javax.persistence.Table(name = NAME_TO_HASH_TABLE_NAME)
|
||||||
class PersistentIdentityNames(
|
class PersistentIdentityNames(
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "name", length = 128, nullable = false)
|
@Column(name = NAME_COLUMN_NAME, length = 128, nullable = false)
|
||||||
var name: String = "",
|
var name: String = "",
|
||||||
|
|
||||||
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = true)
|
@Column(name = PK_HASH_COLUMN_NAME, length = MAX_HASH_HEX_SIZE, nullable = false)
|
||||||
var publicKeyHash: String? = ""
|
var publicKeyHash: String = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
private lateinit var _caCertStore: CertStore
|
private lateinit var _caCertStore: CertStore
|
||||||
@ -156,11 +162,11 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri
|
|||||||
principalToParties.addWithDuplicatesAllowed(identity.name, key, false)
|
principalToParties.addWithDuplicatesAllowed(identity.name, key, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val parentId = mapToKey(identityCertChain[1].publicKey)
|
val parentId = identityCertChain[1].publicKey.toStringShort()
|
||||||
return keyToParties[parentId]
|
return keyToParties[parentId]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun certificateFromKey(owningKey: PublicKey): PartyAndCertificate? = database.transaction { keyToParties[mapToKey(owningKey)] }
|
override fun certificateFromKey(owningKey: PublicKey): PartyAndCertificate? = database.transaction { keyToParties[owningKey.toStringShort()] }
|
||||||
|
|
||||||
private fun certificateFromCordaX500Name(name: CordaX500Name): PartyAndCertificate? {
|
private fun certificateFromCordaX500Name(name: CordaX500Name): PartyAndCertificate? {
|
||||||
return database.transaction {
|
return database.transaction {
|
||||||
|
@ -81,7 +81,8 @@ class BasicHSMKeyManagementService(cacheFactory: NamedCacheFactory,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val keys: Set<PublicKey> get() {
|
override val keys: Set<PublicKey>
|
||||||
|
get() {
|
||||||
return database.transaction {
|
return database.transaction {
|
||||||
val set = LinkedHashSet<PublicKey>(originalKeysMap.keys)
|
val set = LinkedHashSet<PublicKey>(originalKeysMap.keys)
|
||||||
keysMap.allPersisted.use { it.forEach { set += it.first } }
|
keysMap.allPersisted.use { it.forEach { set += it.first } }
|
||||||
|
@ -7,7 +7,6 @@ import net.corda.core.serialization.serialize
|
|||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.utilities.debug
|
import net.corda.core.utilities.debug
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.core.internal.NODE_INFO_DIRECTORY
|
|
||||||
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
||||||
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
|
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
@ -82,8 +81,10 @@ class NodeInfoWatcher(private val nodePath: Path,
|
|||||||
val processedPaths = HashSet<Path>()
|
val processedPaths = HashSet<Path>()
|
||||||
val result = nodeInfosDir.list { paths ->
|
val result = nodeInfosDir.list { paths ->
|
||||||
paths
|
paths
|
||||||
.filter { logger.debug { "Examining $it" }
|
.filter {
|
||||||
true}
|
logger.debug { "Examining $it" }
|
||||||
|
true
|
||||||
|
}
|
||||||
.filter { it.isRegularFile() }
|
.filter { it.isRegularFile() }
|
||||||
.filter { file ->
|
.filter { file ->
|
||||||
val lastModifiedTime = file.lastModifiedTime()
|
val lastModifiedTime = file.lastModifiedTime()
|
||||||
|
@ -41,7 +41,6 @@ open class PersistentNetworkMapCache(cacheFactory: NamedCacheFactory,
|
|||||||
private val database: CordaPersistence,
|
private val database: CordaPersistence,
|
||||||
private val identityService: IdentityService) : NetworkMapCacheInternal, SingletonSerializeAsToken() {
|
private val identityService: IdentityService) : NetworkMapCacheInternal, SingletonSerializeAsToken() {
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val logger = contextLogger()
|
private val logger = contextLogger()
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,8 @@ class DBTransactionStorage(private val database: CordaPersistence, cacheFactory:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
val transactions: List<SignedTransaction> get() = database.transaction { snapshot() }
|
val transactions: List<SignedTransaction>
|
||||||
|
get() = database.transaction { snapshot() }
|
||||||
|
|
||||||
private fun snapshot(): List<SignedTransaction> {
|
private fun snapshot(): List<SignedTransaction> {
|
||||||
return txStorage.content.allPersisted.use {
|
return txStorage.content.allPersisted.use {
|
||||||
@ -241,6 +242,7 @@ class DBTransactionStorage(private val database: CordaPersistence, cacheFactory:
|
|||||||
stx.txBits,
|
stx.txBits,
|
||||||
Collections.unmodifiableList(stx.sigs),
|
Collections.unmodifiableList(stx.sigs),
|
||||||
status)
|
status)
|
||||||
|
|
||||||
fun toSignedTx() = SignedTransaction(txBits, sigs)
|
fun toSignedTx() = SignedTransaction(txBits, sigs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,20 +7,19 @@ import java.util.*
|
|||||||
import javax.persistence.*
|
import javax.persistence.*
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "pk_hash_to_ext_id_map", indexes = [Index(name = "pk_hash_to_xid_idx", columnList = "public_key_hash")])
|
@Table(name = "pk_hash_to_ext_id_map", indexes = [
|
||||||
|
Index(name = "ext_id_idx", columnList = "external_id")
|
||||||
|
])
|
||||||
class PublicKeyHashToExternalId(
|
class PublicKeyHashToExternalId(
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
@Column(name = "id", unique = true, nullable = false)
|
|
||||||
val key: Long?,
|
|
||||||
|
|
||||||
@Column(name = "external_id", nullable = false)
|
@Column(name = "external_id", nullable = false)
|
||||||
@Type(type = "uuid-char")
|
@Type(type = "uuid-char")
|
||||||
val externalId: UUID,
|
val externalId: UUID,
|
||||||
|
|
||||||
|
@Id
|
||||||
@Column(name = "public_key_hash", nullable = false)
|
@Column(name = "public_key_hash", nullable = false)
|
||||||
val publicKeyHash: String
|
val publicKeyHash: String
|
||||||
|
|
||||||
) {
|
) {
|
||||||
constructor(accountId: UUID, publicKey: PublicKey)
|
constructor(accountId: UUID, publicKey: PublicKey)
|
||||||
: this(null, accountId, publicKey.toStringShort())
|
: this(accountId, publicKey.toStringShort())
|
||||||
}
|
}
|
@ -35,7 +35,7 @@ class PublicKeyToOwningIdentityCacheImpl(private val database: CordaPersistence,
|
|||||||
val queryRoot = criteriaQuery.from(PersistentIdentityService.PersistentIdentity::class.java)
|
val queryRoot = criteriaQuery.from(PersistentIdentityService.PersistentIdentity::class.java)
|
||||||
criteriaQuery.select(criteriaBuilder.count(queryRoot))
|
criteriaQuery.select(criteriaBuilder.count(queryRoot))
|
||||||
criteriaQuery.where(
|
criteriaQuery.where(
|
||||||
criteriaBuilder.equal(queryRoot.get<String>(PersistentIdentityService.PersistentIdentity::publicKeyHash.name), key.hash.toString())
|
criteriaBuilder.equal(queryRoot.get<String>(PersistentIdentityService.PersistentIdentity::publicKeyHash.name), key.toStringShort())
|
||||||
)
|
)
|
||||||
val query = session.createQuery(criteriaQuery)
|
val query = session.createQuery(criteriaQuery)
|
||||||
query.uniqueResult() > 0
|
query.uniqueResult() > 0
|
||||||
|
@ -144,8 +144,7 @@ class CheckpointDumper(private val checkpointStorage: CheckpointStorage, private
|
|||||||
val instance = checkpointHook.objectOrNewInstance()
|
val instance = checkpointHook.objectOrNewInstance()
|
||||||
val checkpointIdField = instance.declaredField<UUID>(instance.javaClass, "checkpointId")
|
val checkpointIdField = instance.declaredField<UUID>(instance.javaClass, "checkpointId")
|
||||||
checkpointIdField.value = checkpointId.uuid
|
checkpointIdField.value = checkpointId.uuid
|
||||||
}
|
} catch (e: Exception) {
|
||||||
catch (e: Exception) {
|
|
||||||
log.error("Checkpoint agent instrumentation failed for checkpointId: $checkpointId\n. ${e.message}")
|
log.error("Checkpoint agent instrumentation failed for checkpointId: $checkpointId\n. ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,6 +382,7 @@ class CheckpointDumper(private val checkpointStorage: CheckpointStorage, private
|
|||||||
writeObjectField("ourSessionId", value.sourceSessionId)
|
writeObjectField("ourSessionId", value.sourceSessionId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handledType(): Class<FlowSessionImpl> = FlowSessionImpl::class.java
|
override fun handledType(): Class<FlowSessionImpl> = FlowSessionImpl::class.java
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,6 +402,7 @@ class CheckpointDumper(private val checkpointStorage: CheckpointStorage, private
|
|||||||
}
|
}
|
||||||
gen.writeEndArray()
|
gen.writeEndArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handledType(): Class<Map<Any, Any>> = uncheckedCast(Map::class.java)
|
override fun handledType(): Class<Map<Any, Any>> = uncheckedCast(Map::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ import rx.Observable
|
|||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import java.lang.Integer.min
|
import java.lang.Integer.min
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.util.HashSet
|
import java.util.*
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.*
|
||||||
import javax.annotation.concurrent.ThreadSafe
|
import javax.annotation.concurrent.ThreadSafe
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
@ -217,6 +217,7 @@ class NodeVaultService(
|
|||||||
processAndNotify(updates, previouslySeen)
|
processAndNotify(updates, previouslySeen)
|
||||||
batch.clear()
|
batch.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun processTransactions(txs: Iterable<CoreTransaction>, previouslySeen: Boolean) {
|
fun processTransactions(txs: Iterable<CoreTransaction>, previouslySeen: Boolean) {
|
||||||
for (tx in txs) {
|
for (tx in txs) {
|
||||||
if (batch.isNotEmpty() && tx.javaClass != batch.last().javaClass) {
|
if (batch.isNotEmpty() && tx.javaClass != batch.last().javaClass) {
|
||||||
|
@ -138,8 +138,8 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
|
|||||||
* underlying storage if this races with another database transaction to store a value for the same key.
|
* underlying storage if this races with another database transaction to store a value for the same key.
|
||||||
* @return true if added key was unique, otherwise false
|
* @return true if added key was unique, otherwise false
|
||||||
*/
|
*/
|
||||||
fun addWithDuplicatesAllowed(key: K, value: V, logWarning: Boolean = true): Boolean =
|
fun addWithDuplicatesAllowed(key: K, value: V, logWarning: Boolean = true): Boolean {
|
||||||
set(key, value, logWarning) { k, v ->
|
return set(key, value, logWarning) { k, v ->
|
||||||
val session = currentDBSession()
|
val session = currentDBSession()
|
||||||
val existingEntry = session.find(persistentEntityClass, toPersistentEntityKey(k))
|
val existingEntry = session.find(persistentEntityClass, toPersistentEntityKey(k))
|
||||||
if (existingEntry == null) {
|
if (existingEntry == null) {
|
||||||
@ -149,6 +149,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
|
|||||||
fromPersistentEntity(existingEntry).second
|
fromPersistentEntity(existingEntry).second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associates the specified value with the specified key in this map and persists it.
|
* Associates the specified value with the specified key in this map and persists it.
|
||||||
|
@ -6,11 +6,11 @@ import net.corda.core.internal.notary.NotaryService
|
|||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.node.SerialFilter
|
import net.corda.node.SerialFilter
|
||||||
import net.corda.node.VersionInfo
|
import net.corda.node.VersionInfo
|
||||||
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
|
||||||
import net.corda.node.internal.cordapp.VirtualCordapp
|
import net.corda.node.internal.cordapp.VirtualCordapp
|
||||||
import net.corda.node.services.api.ServiceHubInternal
|
import net.corda.node.services.api.ServiceHubInternal
|
||||||
import net.corda.node.services.config.NotaryConfig
|
import net.corda.node.services.config.NotaryConfig
|
||||||
import net.corda.node.services.transactions.SimpleNotaryService
|
import net.corda.node.services.transactions.SimpleNotaryService
|
||||||
|
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
||||||
import net.corda.notary.experimental.bftsmart.BFTSmartNotaryService
|
import net.corda.notary.experimental.bftsmart.BFTSmartNotaryService
|
||||||
import net.corda.notary.experimental.raft.RaftNotaryService
|
import net.corda.notary.experimental.raft.RaftNotaryService
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package net.corda.node.utilities.registration
|
package net.corda.node.utilities.registration
|
||||||
|
|
||||||
import net.corda.core.crypto.internal.AliasPrivateKey
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
|
import net.corda.core.crypto.internal.AliasPrivateKey
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.node.NodeRegistrationOption
|
import net.corda.node.NodeRegistrationOption
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.nodeapi.internal.cryptoservice.bouncycastle.BCCryptoService
|
|
||||||
import net.corda.nodeapi.internal.config.CertificateStore
|
import net.corda.nodeapi.internal.config.CertificateStore
|
||||||
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
||||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
@ -18,9 +17,10 @@ import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
|||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_VALIDITY_WINDOW
|
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_VALIDITY_WINDOW
|
||||||
|
import net.corda.nodeapi.internal.cryptoservice.CryptoService
|
||||||
import net.corda.nodeapi.internal.cryptoservice.CryptoServiceFactory
|
import net.corda.nodeapi.internal.cryptoservice.CryptoServiceFactory
|
||||||
import net.corda.nodeapi.internal.cryptoservice.SupportedCryptoServices
|
import net.corda.nodeapi.internal.cryptoservice.SupportedCryptoServices
|
||||||
import net.corda.nodeapi.internal.cryptoservice.CryptoService
|
import net.corda.nodeapi.internal.cryptoservice.bouncycastle.BCCryptoService
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
||||||
import org.bouncycastle.operator.ContentSigner
|
import org.bouncycastle.operator.ContentSigner
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
# Build constants exported as resource file to make them visible in Node program
|
# Build constants exported as resource file to make them visible in Node program
|
||||||
# Note: sadly, due to present limitation of IntelliJ-IDEA in processing resource files, these constants cannot be
|
# Note: sadly, due to present limitation of IntelliJ-IDEA in processing resource files, these constants cannot be
|
||||||
# imported from top-level 'constants.properties' file
|
# imported from top-level 'constants.properties' file
|
||||||
|
|
||||||
jolokiaAgentVersion=1.6.1
|
jolokiaAgentVersion=1.6.1
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
|
||||||
|
|
||||||
<changeSet author="R3.Corda" id="1511451595465-1.1" dbms="h2">
|
<changeSet author="R3.Corda" id="1511451595465-1.1" dbms="h2">
|
||||||
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
|
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
<include file="migration/node-core.changelog-v9.xml"/>
|
<include file="migration/node-core.changelog-v9.xml"/>
|
||||||
<include file="migration/node-core.changelog-v10.xml"/>
|
<include file="migration/node-core.changelog-v10.xml"/>
|
||||||
<include file="migration/node-core.changelog-v11.xml"/>
|
<include file="migration/node-core.changelog-v11.xml"/>
|
||||||
|
<include file="migration/node-core.changelog-v12.xml"/>
|
||||||
<!-- This changeset (which creates extra columns in the transactions tables), must be run before the vault state migration (in
|
<!-- This changeset (which creates extra columns in the transactions tables), must be run before the vault state migration (in
|
||||||
vault-schema.changelog-v9.xml), as that will use the current hibernate mappings, and those require all DB columns to be
|
vault-schema.changelog-v9.xml), as that will use the current hibernate mappings, and those require all DB columns to be
|
||||||
created. -->
|
created. -->
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"
|
||||||
|
logicalFilePath="migration/node-services.changelog-init.xml">
|
||||||
|
|
||||||
|
<changeSet author="R3.Corda" id="migrate_pk_hash_to_ext_id">
|
||||||
|
<!-- drop existing "ID" column -->
|
||||||
|
<dropColumn columnName="id"
|
||||||
|
tableName="pk_hash_to_ext_id_map"/>
|
||||||
|
|
||||||
|
<dropIndex tableName="pk_hash_to_ext_id_map" indexName="pk_hash_to_xid_idx"/>
|
||||||
|
|
||||||
|
<!-- create new primary key constraint on key hash -->
|
||||||
|
<addPrimaryKey columnNames="public_key_hash" constraintName="pubkey_hash_to_external_id_pk" tableName="pk_hash_to_ext_id_map"/>
|
||||||
|
|
||||||
|
<createIndex indexName="ext_id_idx" tableName="pk_hash_to_ext_id_map">
|
||||||
|
<column name="external_id"/>
|
||||||
|
</createIndex>
|
||||||
|
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
|
||||||
|
<changeSet author="R3.Corda" id="migrate_identity_service_to_use_publicKey.toShortString()">
|
||||||
|
<customChange class="net.corda.node.migration.PersistentIdentityMigration">
|
||||||
|
</customChange>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
@ -14,7 +14,6 @@ class ThreadContextAdjustingRpcOpsProxyTest {
|
|||||||
private val mockClassloader = mock<ClassLoader>()
|
private val mockClassloader = mock<ClassLoader>()
|
||||||
private val proxy = ThreadContextAdjustingRpcOpsProxy(coreOps, mockClassloader)
|
private val proxy = ThreadContextAdjustingRpcOpsProxy(coreOps, mockClassloader)
|
||||||
|
|
||||||
|
|
||||||
private interface InstrumentedCordaRPCOps : InternalCordaRPCOps {
|
private interface InstrumentedCordaRPCOps : InternalCordaRPCOps {
|
||||||
fun getThreadContextClassLoader(): ClassLoader = Thread.currentThread().contextClassLoader
|
fun getThreadContextClassLoader(): ClassLoader = Thread.currentThread().contextClassLoader
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,120 @@
|
|||||||
|
package net.corda.node.migration
|
||||||
|
|
||||||
|
import liquibase.database.core.H2Database
|
||||||
|
import liquibase.database.jvm.JdbcConnection
|
||||||
|
import net.corda.core.crypto.toStringShort
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
|
import net.corda.core.internal.hash
|
||||||
|
import net.corda.core.utilities.contextLogger
|
||||||
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
|
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||||
|
import net.corda.nodeapi.internal.persistence.contextTransactionOrNull
|
||||||
|
import net.corda.testing.core.*
|
||||||
|
import net.corda.testing.internal.configureDatabase
|
||||||
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
|
import org.hamcrest.CoreMatchers
|
||||||
|
import org.hamcrest.Matcher
|
||||||
|
import org.hamcrest.Matchers.*
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class IdentityServiceToStringShortMigrationTest {
|
||||||
|
companion object {
|
||||||
|
val alice = TestIdentity(ALICE_NAME, 70)
|
||||||
|
val bankOfCorda = TestIdentity(BOC_NAME)
|
||||||
|
val bob = TestIdentity(BOB_NAME, 80)
|
||||||
|
val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20)
|
||||||
|
val ALICE_IDENTITY get() = alice.identity
|
||||||
|
val BOB get() = bob.party
|
||||||
|
val BOB_IDENTITY get() = bob.identity
|
||||||
|
val BOC_IDENTITY get() = bankOfCorda.identity
|
||||||
|
val bob2 = TestIdentity(BOB_NAME, 40)
|
||||||
|
val BOB2_IDENTITY = bob2.identity
|
||||||
|
val logger = contextLogger()
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var liquibaseDB: H2Database
|
||||||
|
lateinit var cordaDB: CordaPersistence
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
cordaDB = configureDatabase(
|
||||||
|
makeTestDataSourceProperties(),
|
||||||
|
DatabaseConfig(),
|
||||||
|
{ null },
|
||||||
|
{ null },
|
||||||
|
ourName = BOB_IDENTITY.name)
|
||||||
|
liquibaseDB = H2Database()
|
||||||
|
liquibaseDB.connection = JdbcConnection(cordaDB.dataSource.connection)
|
||||||
|
liquibaseDB.isAutoCommit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun close() {
|
||||||
|
contextTransactionOrNull?.close()
|
||||||
|
cordaDB.close()
|
||||||
|
liquibaseDB.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveAllIdentitiesWithOldHashString(identities: List<PartyAndCertificate>) {
|
||||||
|
cordaDB.transaction {
|
||||||
|
val groupedIdentities = identities.groupBy { it.name }
|
||||||
|
groupedIdentities.forEach { name, certs ->
|
||||||
|
val persistentIDs = certs.map { PersistentIdentityService.PersistentIdentity(it.owningKey.hash.toString(), it.certPath.encoded) }
|
||||||
|
val persistentName = PersistentIdentityService.PersistentIdentityNames(name.toString(), certs.first().owningKey.hash.toString())
|
||||||
|
persistentIDs.forEach {
|
||||||
|
session.persist(it)
|
||||||
|
}
|
||||||
|
session.persist(persistentName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it should be possible to migrate all existing identities to new hash function`() {
|
||||||
|
val identities = listOf(BOB_IDENTITY, ALICE_IDENTITY, BOC_IDENTITY, dummyNotary.identity, BOB2_IDENTITY)
|
||||||
|
val groupedByNameIdentities = identities.groupBy { it.name }
|
||||||
|
saveAllIdentitiesWithOldHashString(identities)
|
||||||
|
val migration = PersistentIdentityMigration()
|
||||||
|
liquibaseDB.execute(migration.generateStatements(liquibaseDB), listOf())
|
||||||
|
val listOfNamesWithoutPkHash = mutableListOf<CordaX500Name>()
|
||||||
|
identities.forEach {
|
||||||
|
logger.info("Checking: ${it.name}")
|
||||||
|
cordaDB.transaction {
|
||||||
|
val hashToIdentityStatement = database.dataSource.connection.prepareStatement("SELECT ${PersistentIdentityService.PK_HASH_COLUMN_NAME} FROM ${PersistentIdentityService.HASH_TO_IDENTITY_TABLE_NAME} WHERE pk_hash=?")
|
||||||
|
hashToIdentityStatement.setString(1, it.owningKey.toStringShort())
|
||||||
|
val hashToIdentityResultSet = hashToIdentityStatement.executeQuery()
|
||||||
|
|
||||||
|
//check that there is a row for every "new" hash
|
||||||
|
Assert.assertThat(hashToIdentityResultSet.next(), `is`(true))
|
||||||
|
//check that the pk_hash actually matches what we expect (kinda redundant, but deserializing the whole PartyAndCertificate feels like overkill)
|
||||||
|
Assert.assertThat(hashToIdentityResultSet.getString(1), `is`(it.owningKey.toStringShort()))
|
||||||
|
|
||||||
|
val nameToHashStatement = connection.prepareStatement("SELECT ${PersistentIdentityService.NAME_COLUMN_NAME} FROM ${PersistentIdentityService.NAME_TO_HASH_TABLE_NAME} WHERE pk_hash=?")
|
||||||
|
nameToHashStatement.setString(1, it.owningKey.toStringShort())
|
||||||
|
val nameToHashResultSet = nameToHashStatement.executeQuery()
|
||||||
|
|
||||||
|
//if there is no result for this key, this means its an identity that is not stored in the DB (IE, it's been seen after another identity has already been mapped to it)
|
||||||
|
if (nameToHashResultSet.next()) {
|
||||||
|
Assert.assertThat(nameToHashResultSet.getString(1), `is`(anyOf(groupedByNameIdentities.getValue(it.name).map<PartyAndCertificate, Matcher<String>?> { identity -> CoreMatchers.equalTo(identity.name.toString()) })))
|
||||||
|
} else {
|
||||||
|
logger.warn("did not find a PK_HASH for ${it.name}")
|
||||||
|
listOfNamesWithoutPkHash.add(it.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
listOfNamesWithoutPkHash.forEach {
|
||||||
|
//the only time an identity name does not have a PK_HASH is if there are multiple identities associated with that name
|
||||||
|
Assert.assertThat(groupedByNameIdentities[it]?.size, `is`(greaterThan(1)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,15 +3,11 @@ package net.corda.node.migration
|
|||||||
import liquibase.database.Database
|
import liquibase.database.Database
|
||||||
import liquibase.database.jvm.JdbcConnection
|
import liquibase.database.jvm.JdbcConnection
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.*
|
||||||
import net.corda.core.crypto.SecureHash
|
|
||||||
import net.corda.core.crypto.SignableData
|
|
||||||
import net.corda.core.crypto.SignatureMetadata
|
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.NotaryChangeTransactionBuilder
|
import net.corda.core.internal.NotaryChangeTransactionBuilder
|
||||||
import net.corda.core.internal.hash
|
|
||||||
import net.corda.core.internal.packageName
|
import net.corda.core.internal.packageName
|
||||||
import net.corda.core.internal.signWithCert
|
import net.corda.core.internal.signWithCert
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
@ -198,8 +194,8 @@ class VaultStateMigrationTest {
|
|||||||
private fun saveAllIdentities(identities: List<PartyAndCertificate>) {
|
private fun saveAllIdentities(identities: List<PartyAndCertificate>) {
|
||||||
cordaDB.transaction {
|
cordaDB.transaction {
|
||||||
identities.groupBy { it.name }.forEach { name, certs ->
|
identities.groupBy { it.name }.forEach { name, certs ->
|
||||||
val persistentIDs = certs.map { PersistentIdentityService.PersistentIdentity(it.owningKey.hash.toString(), it.certPath.encoded) }
|
val persistentIDs = certs.map { PersistentIdentityService.PersistentIdentity(it.owningKey.toStringShort(), it.certPath.encoded) }
|
||||||
val persistentName = PersistentIdentityService.PersistentIdentityNames(name.toString(), certs.first().owningKey.hash.toString())
|
val persistentName = PersistentIdentityService.PersistentIdentityNames(name.toString(), certs.first().owningKey.toStringShort())
|
||||||
persistentIDs.forEach { session.save(it) }
|
persistentIDs.forEach { session.save(it) }
|
||||||
session.save(persistentName)
|
session.save(persistentName)
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,10 @@ import net.corda.core.internal.*
|
|||||||
import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION
|
import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION
|
||||||
import net.corda.core.node.ServicesForResolution
|
import net.corda.core.node.ServicesForResolution
|
||||||
import net.corda.core.node.services.AttachmentId
|
import net.corda.core.node.services.AttachmentId
|
||||||
import net.corda.core.node.services.vault.*
|
|
||||||
import net.corda.core.node.services.vault.AttachmentQueryCriteria.AttachmentsQueryCriteria
|
import net.corda.core.node.services.vault.AttachmentQueryCriteria.AttachmentsQueryCriteria
|
||||||
|
import net.corda.core.node.services.vault.AttachmentSort
|
||||||
|
import net.corda.core.node.services.vault.Builder
|
||||||
|
import net.corda.core.node.services.vault.Sort
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.services.transactions.PersistentUniquenessProvider
|
import net.corda.node.services.transactions.PersistentUniquenessProvider
|
||||||
import net.corda.nodeapi.exceptions.DuplicateAttachmentException
|
import net.corda.nodeapi.exceptions.DuplicateAttachmentException
|
||||||
|
@ -58,7 +58,8 @@ class ObserverNodeTransactionTests {
|
|||||||
|
|
||||||
fun sendTransactionToObserver(transactionIdx: Int, node: TestStartedNode, regulator: TestStartedNode) {
|
fun sendTransactionToObserver(transactionIdx: Int, node: TestStartedNode, regulator: TestStartedNode) {
|
||||||
val transactionList = node.services.validatedTransactions.track().snapshot
|
val transactionList = node.services.validatedTransactions.track().snapshot
|
||||||
node.services.startFlow(ReportToCounterparty(regulator.info.singleIdentity(), transactionList[transactionIdx])).resultFuture.getOrThrow()
|
node.services.startFlow(ReportToCounterparty(regulator.info.singleIdentity(), transactionList[transactionIdx]))
|
||||||
|
.resultFuture.getOrThrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendTransactionToObserverOnlyRelevant(transactionIdx: Int, node: TestStartedNode, regulator: TestStartedNode) {
|
fun sendTransactionToObserverOnlyRelevant(transactionIdx: Int, node: TestStartedNode, regulator: TestStartedNode) {
|
||||||
@ -79,7 +80,6 @@ class ObserverNodeTransactionTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Broadcasting an old transaction does not cause 2 unconsumed states`() {
|
fun `Broadcasting an old transaction does not cause 2 unconsumed states`() {
|
||||||
val node = mockNet.createPartyNode(ALICE_NAME)
|
val node = mockNet.createPartyNode(ALICE_NAME)
|
||||||
@ -292,7 +292,6 @@ class ObserverNodeTransactionTests {
|
|||||||
val flow = object : SignTransactionFlow(otherSideSession) {
|
val flow = object : SignTransactionFlow(otherSideSession) {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun checkTransaction(stx: SignedTransaction) {
|
override fun checkTransaction(stx: SignedTransaction) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subFlow(flow)
|
subFlow(flow)
|
||||||
|
@ -465,7 +465,8 @@ class FlowFrameworkTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `initiating flow using unknown AnonymousParty`() {
|
fun `initiating flow using unknown AnonymousParty`() {
|
||||||
val anonymousBob = bobNode.services.keyManagementService.freshKeyAndCert(bobNode.info.legalIdentitiesAndCerts.single(), false).party.anonymise()
|
val anonymousBob = bobNode.services.keyManagementService.freshKeyAndCert(bobNode.info.legalIdentitiesAndCerts.single(), false)
|
||||||
|
.party.anonymise()
|
||||||
bobNode.registerCordappFlowFactory(SendAndReceiveFlow::class) { SingleInlinedSubFlow(it) }
|
bobNode.registerCordappFlowFactory(SendAndReceiveFlow::class) { SingleInlinedSubFlow(it) }
|
||||||
val result = aliceNode.services.startFlow(SendAndReceiveFlow(anonymousBob, "Hello")).resultFuture
|
val result = aliceNode.services.startFlow(SendAndReceiveFlow(anonymousBob, "Hello")).resultFuture
|
||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
|
@ -3,7 +3,10 @@ package net.corda.node.services.vault
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.nhaarman.mockito_kotlin.*
|
import com.nhaarman.mockito_kotlin.*
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.FinalityFlow
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.FlowSession
|
||||||
|
import net.corda.core.flows.InitiatingFlow
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.internal.FlowStateMachine
|
import net.corda.core.internal.FlowStateMachine
|
||||||
import net.corda.core.internal.uncheckedCast
|
import net.corda.core.internal.uncheckedCast
|
||||||
@ -19,8 +22,8 @@ import net.corda.core.utilities.NonEmptySet
|
|||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
|
||||||
import net.corda.node.services.api.VaultServiceInternal
|
import net.corda.node.services.api.VaultServiceInternal
|
||||||
|
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.flows.registerCoreFlowFactory
|
import net.corda.testing.flows.registerCoreFlowFactory
|
||||||
|
@ -83,6 +83,7 @@ data class NodeParameters(
|
|||||||
maximumHeapSize = maximumHeapSize,
|
maximumHeapSize = maximumHeapSize,
|
||||||
additionalCordapps = additionalCordapps
|
additionalCordapps = additionalCordapps
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
providedName: CordaX500Name?,
|
providedName: CordaX500Name?,
|
||||||
rpcUsers: List<User>,
|
rpcUsers: List<User>,
|
||||||
|
@ -39,7 +39,6 @@ import net.corda.nodeapi.internal.crypto.X509Utilities
|
|||||||
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
||||||
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
|
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
|
||||||
import net.corda.notary.experimental.raft.RaftConfig
|
import net.corda.notary.experimental.raft.RaftConfig
|
||||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
|
||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.BOB_NAME
|
import net.corda.testing.core.BOB_NAME
|
||||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||||
|
@ -58,8 +58,8 @@ class DBRunnerExtension : Extension, BeforeAllCallback, AfterAllCallback, Before
|
|||||||
val rootContext = context?.root ?: return null
|
val rootContext = context?.root ?: return null
|
||||||
|
|
||||||
val testClass = context.testClass.orElse(null) ?: return null
|
val testClass = context.testClass.orElse(null) ?: return null
|
||||||
val annotation = testClass.requiredDb ?:
|
val annotation = testClass.requiredDb
|
||||||
throw IllegalStateException("Test run with DBRunnerExtension is not annotated with @RequiresDb")
|
?: throw IllegalStateException("Test run with DBRunnerExtension is not annotated with @RequiresDb")
|
||||||
val groupName = annotation.group
|
val groupName = annotation.group
|
||||||
val defaultContextClassName = annotation.defaultContextClassName
|
val defaultContextClassName = annotation.defaultContextClassName
|
||||||
|
|
||||||
@ -88,7 +88,8 @@ class DBRunnerExtension : Extension, BeforeAllCallback, AfterAllCallback, Before
|
|||||||
else annotation.annotationClass.java.findAnnotations(annotationClass)
|
else annotation.annotationClass.java.findAnnotations(annotationClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val Annotation.isInternal: Boolean get() = annotationClass.java.name.run {
|
private val Annotation.isInternal: Boolean
|
||||||
|
get() = annotationClass.java.name.run {
|
||||||
startsWith("java.lang") ||
|
startsWith("java.lang") ||
|
||||||
startsWith("org.junit") ||
|
startsWith("org.junit") ||
|
||||||
startsWith("kotlin")
|
startsWith("kotlin")
|
||||||
|
@ -16,5 +16,4 @@ class NoOpTestDatabaseContext : TestDatabaseContext {
|
|||||||
override fun afterTest(teardownSql: List<String>) {}
|
override fun afterTest(teardownSql: List<String>) {}
|
||||||
|
|
||||||
override fun close() {}
|
override fun close() {}
|
||||||
|
|
||||||
}
|
}
|
@ -3,7 +3,6 @@ package net.corda.testing.internal.db
|
|||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.lang.IllegalStateException
|
|
||||||
|
|
||||||
class AssertingTestDatabaseContext : TestDatabaseContext {
|
class AssertingTestDatabaseContext : TestDatabaseContext {
|
||||||
|
|
||||||
@ -57,5 +56,4 @@ class AssertingTestDatabaseContext : TestDatabaseContext {
|
|||||||
throw IllegalStateException("Assertion failed: ${e.message}")
|
throw IllegalStateException("Assertion failed: ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,7 +15,5 @@ class GroupAMoreTests {
|
|||||||
@SpecialSql1
|
@SpecialSql1
|
||||||
@SpecialSql2
|
@SpecialSql2
|
||||||
fun moreSpecialSqlRequired() {
|
fun moreSpecialSqlRequired() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -14,13 +14,10 @@ class GroupATests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun noSpecialSqlRequired() {
|
fun noSpecialSqlRequired() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SpecialSql1
|
@SpecialSql1
|
||||||
fun someSpecialSqlRequired() {
|
fun someSpecialSqlRequired() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -13,13 +13,10 @@ class GroupBTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun noSpecialSqlRequired() {
|
fun noSpecialSqlRequired() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SpecialSql1
|
@SpecialSql1
|
||||||
fun someSpecialSqlRequired() {
|
fun someSpecialSqlRequired() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -13,7 +13,8 @@
|
|||||||
<Appenders>
|
<Appenders>
|
||||||
<Console name="Console-Appender" target="SYSTEM_OUT">
|
<Console name="Console-Appender" target="SYSTEM_OUT">
|
||||||
<PatternLayout>
|
<PatternLayout>
|
||||||
<ScriptPatternSelector defaultPattern="%highlight{[%level{length=5}] %date{HH:mm:ss,SSS} [%t] %c{2}.%method - %msg%n}{INFO=white,WARN=red,FATAL=bright red}">
|
<ScriptPatternSelector
|
||||||
|
defaultPattern="%highlight{[%level{length=5}] %date{HH:mm:ss,SSS} [%t] %c{2}.%method - %msg%n}{INFO=white,WARN=red,FATAL=bright red}">
|
||||||
<Script name="MDCSelector" language="javascript"><![CDATA[
|
<Script name="MDCSelector" language="javascript"><![CDATA[
|
||||||
result = null;
|
result = null;
|
||||||
if (!logEvent.getContextData().size() == 0) {
|
if (!logEvent.getContextData().size() == 0) {
|
||||||
@ -24,7 +25,8 @@
|
|||||||
result;
|
result;
|
||||||
]]>
|
]]>
|
||||||
</Script>
|
</Script>
|
||||||
<PatternMatch key="WithMDC" pattern="%highlight{[%level{length=5}] %date{HH:mm:ss,SSS} [%t] %c{2}.%method - %msg %X%n}{INFO=white,WARN=red,FATAL=bright red}"/>
|
<PatternMatch key="WithMDC"
|
||||||
|
pattern="%highlight{[%level{length=5}] %date{HH:mm:ss,SSS} [%t] %c{2}.%method - %msg %X%n}{INFO=white,WARN=red,FATAL=bright red}"/>
|
||||||
</ScriptPatternSelector>
|
</ScriptPatternSelector>
|
||||||
</PatternLayout>
|
</PatternLayout>
|
||||||
<ThresholdFilter level="trace"/>
|
<ThresholdFilter level="trace"/>
|
||||||
|
@ -15,7 +15,6 @@ class DummyContractV2 : UpgradedContractWithLegacyConstraint<DummyContract.State
|
|||||||
companion object {
|
companion object {
|
||||||
const val PROGRAM_ID: ContractClassName = "net.corda.testing.contracts.DummyContractV2"
|
const val PROGRAM_ID: ContractClassName = "net.corda.testing.contracts.DummyContractV2"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An overload of move for just one input state.
|
* An overload of move for just one input state.
|
||||||
*/
|
*/
|
||||||
|
@ -8,13 +8,13 @@ import javassist.ClassPool
|
|||||||
import javassist.CtClass
|
import javassist.CtClass
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.internal.ThreadBox
|
||||||
import net.corda.core.utilities.debug
|
import net.corda.core.utilities.debug
|
||||||
|
import net.corda.tools.CheckpointAgent.Companion.graphDepth
|
||||||
import net.corda.tools.CheckpointAgent.Companion.instrumentClassname
|
import net.corda.tools.CheckpointAgent.Companion.instrumentClassname
|
||||||
import net.corda.tools.CheckpointAgent.Companion.instrumentType
|
import net.corda.tools.CheckpointAgent.Companion.instrumentType
|
||||||
import net.corda.tools.CheckpointAgent.Companion.log
|
import net.corda.tools.CheckpointAgent.Companion.log
|
||||||
import net.corda.tools.CheckpointAgent.Companion.maximumSize
|
import net.corda.tools.CheckpointAgent.Companion.maximumSize
|
||||||
import net.corda.tools.CheckpointAgent.Companion.minimumSize
|
import net.corda.tools.CheckpointAgent.Companion.minimumSize
|
||||||
import net.corda.tools.CheckpointAgent.Companion.printOnce
|
import net.corda.tools.CheckpointAgent.Companion.printOnce
|
||||||
import net.corda.tools.CheckpointAgent.Companion.graphDepth
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.lang.instrument.ClassFileTransformer
|
import java.lang.instrument.ClassFileTransformer
|
||||||
@ -65,24 +65,34 @@ class CheckpointAgent {
|
|||||||
if (nvpItem.size == 2) {
|
if (nvpItem.size == 2) {
|
||||||
when (nvpItem[0].trim()) {
|
when (nvpItem[0].trim()) {
|
||||||
"instrumentClassname" -> instrumentClassname = nvpItem[1]
|
"instrumentClassname" -> instrumentClassname = nvpItem[1]
|
||||||
"instrumentType" -> try { instrumentType = InstrumentationType.valueOf(nvpItem[1].toUpperCase()) } catch (e: Exception) {
|
"instrumentType" -> try {
|
||||||
|
instrumentType = InstrumentationType.valueOf(nvpItem[1].toUpperCase())
|
||||||
|
} catch (e: Exception) {
|
||||||
display("Invalid value: ${nvpItem[1]}. Please specify read or write.")
|
display("Invalid value: ${nvpItem[1]}. Please specify read or write.")
|
||||||
}
|
}
|
||||||
"minimumSize" -> try { minimumSize = nvpItem[1].toInt() } catch (e: NumberFormatException) {
|
"minimumSize" -> try {
|
||||||
display("Invalid value: ${nvpItem[1]}. Please specify an integer value.") }
|
minimumSize = nvpItem[1].toInt()
|
||||||
"maximumSize" -> try { maximumSize = nvpItem[1].toInt() } catch (e: NumberFormatException) {
|
} catch (e: NumberFormatException) {
|
||||||
display("Invalid value: ${nvpItem[1]}. Please specify an integer value.")
|
display("Invalid value: ${nvpItem[1]}. Please specify an integer value.")
|
||||||
}
|
}
|
||||||
"graphDepth" -> try { graphDepth = nvpItem[1].toInt() } catch (e: NumberFormatException) {
|
"maximumSize" -> try {
|
||||||
|
maximumSize = nvpItem[1].toInt()
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
display("Invalid value: ${nvpItem[1]}. Please specify an integer value.")
|
display("Invalid value: ${nvpItem[1]}. Please specify an integer value.")
|
||||||
}
|
}
|
||||||
"printOnce" -> try { printOnce = nvpItem[1].toBoolean() } catch (e: Exception) {
|
"graphDepth" -> try {
|
||||||
|
graphDepth = nvpItem[1].toInt()
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
display("Invalid value: ${nvpItem[1]}. Please specify an integer value.")
|
||||||
|
}
|
||||||
|
"printOnce" -> try {
|
||||||
|
printOnce = nvpItem[1].toBoolean()
|
||||||
|
} catch (e: Exception) {
|
||||||
display("Invalid value: ${nvpItem[1]}. Please specify true or false.")
|
display("Invalid value: ${nvpItem[1]}. Please specify true or false.")
|
||||||
}
|
}
|
||||||
else -> display("Invalid argument: $nvpItem")
|
else -> display("Invalid argument: $nvpItem")
|
||||||
}
|
}
|
||||||
}
|
} else display("Missing value for argument: $nvpItem")
|
||||||
else display("Missing value for argument: $nvpItem")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println("Running Checkpoint agent with following arguments: instrumentClassname=$instrumentClassname, instrumentType=$instrumentType, minimumSize=$minimumSize, maximumSize=$maximumSize, graphDepth=$graphDepth, printOnce=$printOnce\n")
|
println("Running Checkpoint agent with following arguments: instrumentClassname=$instrumentClassname, instrumentType=$instrumentType, minimumSize=$minimumSize, maximumSize=$maximumSize, graphDepth=$graphDepth, printOnce=$printOnce\n")
|
||||||
@ -207,8 +217,7 @@ object CheckpointHook : ClassFileTransformer {
|
|||||||
val numberValue = value as Array<Number>
|
val numberValue = value as Array<Number>
|
||||||
log.debug { "readFieldExit array of number: $clazz = ${numberValue.joinToString(",")}" }
|
log.debug { "readFieldExit array of number: $clazz = ${numberValue.joinToString(",")}" }
|
||||||
return numberValue.joinToString(",")
|
return numberValue.joinToString(",")
|
||||||
}
|
} else if (clazz == Array<Boolean>::class.java) {
|
||||||
else if (clazz == Array<Boolean>::class.java) {
|
|
||||||
val arrayValue = value as Array<Boolean>
|
val arrayValue = value as Array<Boolean>
|
||||||
log.debug { "readFieldExit array of boolean: $clazz = ${arrayValue.joinToString(",")}" }
|
log.debug { "readFieldExit array of boolean: $clazz = ${arrayValue.joinToString(",")}" }
|
||||||
return arrayValue.joinToString(",")
|
return arrayValue.joinToString(",")
|
||||||
@ -226,38 +235,31 @@ object CheckpointHook : ClassFileTransformer {
|
|||||||
val arrayValue = value as CharArray
|
val arrayValue = value as CharArray
|
||||||
log.debug { "readFieldExit char array: $clazz = ${arrayValue.joinToString("")}" }
|
log.debug { "readFieldExit char array: $clazz = ${arrayValue.joinToString("")}" }
|
||||||
return arrayValue.joinToString("")
|
return arrayValue.joinToString("")
|
||||||
}
|
} else if (clazz == ByteArray::class.java) {
|
||||||
else if (clazz == ByteArray::class.java) {
|
|
||||||
val arrayValue = value as ByteArray
|
val arrayValue = value as ByteArray
|
||||||
log.debug { "readFieldExit byte array: $clazz = ${byteArrayToHex(arrayValue)}" }
|
log.debug { "readFieldExit byte array: $clazz = ${byteArrayToHex(arrayValue)}" }
|
||||||
return byteArrayToHex(arrayValue)
|
return byteArrayToHex(arrayValue)
|
||||||
}
|
} else if (clazz == ShortArray::class.java) {
|
||||||
else if (clazz == ShortArray::class.java) {
|
|
||||||
val arrayValue = value as ShortArray
|
val arrayValue = value as ShortArray
|
||||||
log.debug { "readFieldExit short array: $clazz = ${arrayValue.joinToString(",")}" }
|
log.debug { "readFieldExit short array: $clazz = ${arrayValue.joinToString(",")}" }
|
||||||
return arrayValue.joinToString(",")
|
return arrayValue.joinToString(",")
|
||||||
}
|
} else if (clazz == IntArray::class.java) {
|
||||||
else if (clazz == IntArray::class.java) {
|
|
||||||
val arrayValue = value as IntArray
|
val arrayValue = value as IntArray
|
||||||
log.debug { "readFieldExit int array: $clazz = ${arrayValue.joinToString(",")}" }
|
log.debug { "readFieldExit int array: $clazz = ${arrayValue.joinToString(",")}" }
|
||||||
return arrayValue.joinToString(",")
|
return arrayValue.joinToString(",")
|
||||||
}
|
} else if (clazz == LongArray::class.java) {
|
||||||
else if (clazz == LongArray::class.java) {
|
|
||||||
val arrayValue = value as LongArray
|
val arrayValue = value as LongArray
|
||||||
log.debug { "readFieldExit long array: $clazz = ${arrayValue.joinToString(",")}" }
|
log.debug { "readFieldExit long array: $clazz = ${arrayValue.joinToString(",")}" }
|
||||||
return arrayValue.joinToString(",")
|
return arrayValue.joinToString(",")
|
||||||
}
|
} else if (clazz == FloatArray::class.java) {
|
||||||
else if (clazz == FloatArray::class.java) {
|
|
||||||
val arrayValue = value as FloatArray
|
val arrayValue = value as FloatArray
|
||||||
log.debug { "readFieldExit float array: $clazz = ${arrayValue.joinToString(",")}" }
|
log.debug { "readFieldExit float array: $clazz = ${arrayValue.joinToString(",")}" }
|
||||||
return arrayValue.joinToString(",")
|
return arrayValue.joinToString(",")
|
||||||
}
|
} else if (clazz == DoubleArray::class.java) {
|
||||||
else if (clazz == DoubleArray::class.java) {
|
|
||||||
val arrayValue = value as DoubleArray
|
val arrayValue = value as DoubleArray
|
||||||
log.debug { "readFieldExit double array: $clazz = ${arrayValue.joinToString(",")}" }
|
log.debug { "readFieldExit double array: $clazz = ${arrayValue.joinToString(",")}" }
|
||||||
return arrayValue.joinToString(",")
|
return arrayValue.joinToString(",")
|
||||||
}
|
} else if (clazz == BooleanArray::class.java) {
|
||||||
else if (clazz == BooleanArray::class.java) {
|
|
||||||
val arrayValue = value as BooleanArray
|
val arrayValue = value as BooleanArray
|
||||||
log.debug { "readFieldExit boolean array: $clazz = ${arrayValue.joinToString(",")}" }
|
log.debug { "readFieldExit boolean array: $clazz = ${arrayValue.joinToString(",")}" }
|
||||||
return arrayValue.joinToString(",")
|
return arrayValue.joinToString(",")
|
||||||
@ -340,22 +342,18 @@ object CheckpointHook : ClassFileTransformer {
|
|||||||
is StatsTree.Object -> {
|
is StatsTree.Object -> {
|
||||||
if (printOnce && identityInfo.refCount > 1) {
|
if (printOnce && identityInfo.refCount > 1) {
|
||||||
log.debug { "Skipping $statsInfo, $statsTree (count:${identityInfo.refCount})" }
|
log.debug { "Skipping $statsInfo, $statsTree (count:${identityInfo.refCount})" }
|
||||||
}
|
} else if (indent / 2 < graphDepth) {
|
||||||
else if (indent/2 < graphDepth) {
|
|
||||||
builder.append(String.format("%03d:", indent / 2))
|
builder.append(String.format("%03d:", indent / 2))
|
||||||
builder.append(CharArray(indent) { ' ' })
|
builder.append(CharArray(indent) { ' ' })
|
||||||
builder.append(" ${statsInfo.fieldName} ")
|
builder.append(" ${statsInfo.fieldName} ")
|
||||||
if (statsInfo.fieldType != null && statsInfo.fieldType.isArray) {
|
if (statsInfo.fieldType != null && statsInfo.fieldType.isArray) {
|
||||||
val arrayValue = (statsTree.value as Array<Any?>)
|
val arrayValue = (statsTree.value as Array<Any?>)
|
||||||
builder.append("${statsInfo.fieldType} (array length:${arrayValue.size})")
|
builder.append("${statsInfo.fieldType} (array length:${arrayValue.size})")
|
||||||
}
|
} else if (statsInfo.fieldType != null && statsTree.value is Collection<*>) {
|
||||||
else if (statsInfo.fieldType != null && statsTree.value is Collection<*>) {
|
|
||||||
builder.append("${statsInfo.fieldType} (collection size:${statsTree.value.size})")
|
builder.append("${statsInfo.fieldType} (collection size:${statsTree.value.size})")
|
||||||
}
|
} else if (statsInfo.fieldType != null && statsTree.value is Map<*, *>) {
|
||||||
else if (statsInfo.fieldType != null && statsTree.value is Map<*,*>) {
|
|
||||||
builder.append("${statsInfo.fieldType} (map size:${statsTree.value.size})")
|
builder.append("${statsInfo.fieldType} (map size:${statsTree.value.size})")
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
builder.append("${statsTree.className} (hash:${statsTree.value?.hashCode()}) (count:${identityInfo.refCount})")
|
builder.append("${statsTree.className} (hash:${statsTree.value?.hashCode()}) (count:${identityInfo.refCount})")
|
||||||
}
|
}
|
||||||
builder.append(" ")
|
builder.append(" ")
|
||||||
@ -476,8 +474,7 @@ fun readTrees(events: List<StatsEvent>, index: Int, idMap: IdentityHashMap<Any,
|
|||||||
idMap[event.value] = IdentityInfo(identityInfo.tree, identityInfo.refCount + 1)
|
idMap[event.value] = IdentityInfo(identityInfo.tree, identityInfo.refCount + 1)
|
||||||
log.debug { "Skipping repeated StatsEvent.ObjectField: ${event.value} (hashcode:${event.value!!.hashCode()}) (count:${idMap[event.value]?.refCount})" }
|
log.debug { "Skipping repeated StatsEvent.ObjectField: ${event.value} (hashcode:${event.value!!.hashCode()}) (count:${idMap[event.value]?.refCount})" }
|
||||||
identityInfo
|
identityInfo
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
IdentityInfo(StatsTree.Loop(0), 1)
|
IdentityInfo(StatsTree.Loop(0), 1)
|
||||||
}
|
}
|
||||||
trees += StatsInfo(event.fieldName, event.fieldType) to identityInfo
|
trees += StatsInfo(event.fieldName, event.fieldType) to identityInfo
|
||||||
|
@ -22,6 +22,7 @@ interface NetworkBuilder {
|
|||||||
fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder
|
fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder
|
||||||
/** Sets network name */
|
/** Sets network name */
|
||||||
fun withNetworkName(networkName: String): NetworkBuilder
|
fun withNetworkName(networkName: String): NetworkBuilder
|
||||||
|
|
||||||
fun withBasedir(baseDir: File): NetworkBuilder
|
fun withBasedir(baseDir: File): NetworkBuilder
|
||||||
fun withBackend(backendType: Backend.BackendType): NetworkBuilder
|
fun withBackend(backendType: Backend.BackendType): NetworkBuilder
|
||||||
fun withBackendOptions(options: Map<String, String>): NetworkBuilder
|
fun withBackendOptions(options: Map<String, String>): NetworkBuilder
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.corda.networkbuilder.cli
|
package net.corda.networkbuilder.cli
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.networkbuilder.Constants
|
import net.corda.networkbuilder.Constants
|
||||||
import net.corda.networkbuilder.NetworkBuilder
|
import net.corda.networkbuilder.NetworkBuilder
|
||||||
import net.corda.networkbuilder.backends.Backend
|
import net.corda.networkbuilder.backends.Backend
|
||||||
@ -8,8 +10,6 @@ import net.corda.networkbuilder.context.Context
|
|||||||
import net.corda.networkbuilder.nodes.NodeAdder
|
import net.corda.networkbuilder.nodes.NodeAdder
|
||||||
import net.corda.networkbuilder.nodes.NodeInstantiator
|
import net.corda.networkbuilder.nodes.NodeInstantiator
|
||||||
import net.corda.networkbuilder.toSingleFuture
|
import net.corda.networkbuilder.toSingleFuture
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import net.corda.core.utilities.getOrThrow
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class CommandLineInterface {
|
class CommandLineInterface {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package net.corda.networkbuilder.context
|
package net.corda.networkbuilder.context
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.networkbuilder.Constants
|
import net.corda.networkbuilder.Constants
|
||||||
import net.corda.networkbuilder.backends.Backend
|
import net.corda.networkbuilder.backends.Backend
|
||||||
import net.corda.networkbuilder.nodes.NodeInstanceRequest
|
import net.corda.networkbuilder.nodes.NodeInstanceRequest
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet
|
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import javafx.scene.layout.HBox
|
|||||||
import javafx.scene.layout.Priority
|
import javafx.scene.layout.Priority
|
||||||
import javafx.scene.layout.VBox
|
import javafx.scene.layout.VBox
|
||||||
import javafx.stage.DirectoryChooser
|
import javafx.stage.DirectoryChooser
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.networkbuilder.Constants
|
import net.corda.networkbuilder.Constants
|
||||||
import net.corda.networkbuilder.GuiUtils
|
import net.corda.networkbuilder.GuiUtils
|
||||||
import net.corda.networkbuilder.NetworkBuilder
|
import net.corda.networkbuilder.NetworkBuilder
|
||||||
@ -21,7 +22,6 @@ import net.corda.networkbuilder.backends.Backend
|
|||||||
import net.corda.networkbuilder.baseArgs
|
import net.corda.networkbuilder.baseArgs
|
||||||
import net.corda.networkbuilder.context.Context
|
import net.corda.networkbuilder.context.Context
|
||||||
import net.corda.networkbuilder.nodes.*
|
import net.corda.networkbuilder.nodes.*
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import org.apache.commons.lang3.RandomStringUtils
|
import org.apache.commons.lang3.RandomStringUtils
|
||||||
import org.controlsfx.control.SegmentedButton
|
import org.controlsfx.control.SegmentedButton
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
@ -104,6 +104,7 @@ class BootstrapperView : View("Corda Network Builder") {
|
|||||||
override fun get(index: Int): String {
|
override fun get(index: Int): String {
|
||||||
return controller.foundNodes[index].id
|
return controller.foundNodes[index].id
|
||||||
}
|
}
|
||||||
|
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = controller.foundNodes.size
|
get() = controller.foundNodes.size
|
||||||
}
|
}
|
||||||
@ -291,7 +292,6 @@ class BootstrapperView : View("Corda Network Builder") {
|
|||||||
unsortedNodes.add(NodeTemplateInfo(it.name, NodeType.NOTARY))
|
unsortedNodes.add(NodeTemplateInfo(it.name, NodeType.NOTARY))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var baseDir = SimpleObjectProperty<File>(null)
|
var baseDir = SimpleObjectProperty<File>(null)
|
||||||
@ -363,7 +363,6 @@ class BootstrapperView : View("Corda Network Builder") {
|
|||||||
val locallyReachableAddress: String,
|
val locallyReachableAddress: String,
|
||||||
val rpcPort: Int,
|
val rpcPort: Int,
|
||||||
val sshPort: Int)
|
val sshPort: Int)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FoundNodeTableEntry(val id: String, @Volatile var count: Int = 1)
|
data class FoundNodeTableEntry(val id: String, @Volatile var count: Int = 1)
|
@ -1,7 +1,7 @@
|
|||||||
package net.corda.networkbuilder.gui
|
package net.corda.networkbuilder.gui
|
||||||
|
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import tornadofx.App
|
import tornadofx.*
|
||||||
|
|
||||||
class Gui : App(BootstrapperView::class) {
|
class Gui : App(BootstrapperView::class) {
|
||||||
override fun start(stage: Stage) {
|
override fun start(stage: Stage) {
|
||||||
|
@ -19,7 +19,6 @@ open class CopiedNode(configFile: File, baseDirectory: File,
|
|||||||
return copiedNodeConfig
|
return copiedNodeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun builtNode(nodeConfig: NodeConfiguration, imageId: String): BuiltNode {
|
fun builtNode(nodeConfig: NodeConfiguration, imageId: String): BuiltNode {
|
||||||
return BuiltNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir, nodeConfig, imageId)
|
return BuiltNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir, nodeConfig, imageId)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package net.corda.networkbuilder.nodes
|
package net.corda.networkbuilder.nodes
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.networkbuilder.containers.instance.InstanceInfo
|
import net.corda.networkbuilder.containers.instance.InstanceInfo
|
||||||
import net.corda.networkbuilder.context.Context
|
import net.corda.networkbuilder.context.Context
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
class NodeAdder(val context: Context,
|
class NodeAdder(val context: Context,
|
||||||
@ -13,7 +13,8 @@ class NodeAdder(val context: Context,
|
|||||||
val nodeGroup = context.nodes[nodeGroupName]!!
|
val nodeGroup = context.nodes[nodeGroupName]!!
|
||||||
val nodeInfo = nodeGroup.iterator().next()
|
val nodeInfo = nodeGroup.iterator().next()
|
||||||
val currentNodeSize = nodeGroup.size
|
val currentNodeSize = nodeGroup.size
|
||||||
val newInstanceX500 = x500ToAdd?.toString() ?: nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString()
|
val newInstanceX500 = x500ToAdd?.toString()
|
||||||
|
?: nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString()
|
||||||
val newInstanceName = nodeGroupName + (currentNodeSize)
|
val newInstanceName = nodeGroupName + (currentNodeSize)
|
||||||
val nextNodeInfo = nodeInfo.copy(
|
val nextNodeInfo = nodeInfo.copy(
|
||||||
instanceX500 = newInstanceX500,
|
instanceX500 = newInstanceX500,
|
||||||
|
@ -6,9 +6,9 @@ import com.github.dockerjava.core.command.BuildImageResultCallback
|
|||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import com.typesafe.config.ConfigValueFactory
|
import com.typesafe.config.ConfigValueFactory
|
||||||
import net.corda.networkbuilder.docker.DockerUtils
|
|
||||||
import net.corda.common.configuration.parsing.internal.Configuration
|
import net.corda.common.configuration.parsing.internal.Configuration
|
||||||
import net.corda.common.validation.internal.Validated
|
import net.corda.common.validation.internal.Validated
|
||||||
|
import net.corda.networkbuilder.docker.DockerUtils
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.config.parseAsNodeConfiguration
|
import net.corda.node.services.config.parseAsNodeConfiguration
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
@ -3,8 +3,8 @@ package net.corda.networkbuilder.nodes
|
|||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigException
|
import com.typesafe.config.ConfigException
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import net.corda.networkbuilder.Constants
|
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
|
import net.corda.networkbuilder.Constants
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class NodeFinder(private val dirToSearch: File) {
|
class NodeFinder(private val dirToSearch: File) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package net.corda.networkbuilder.nodes
|
package net.corda.networkbuilder.nodes
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.networkbuilder.Constants
|
import net.corda.networkbuilder.Constants
|
||||||
import net.corda.networkbuilder.containers.instance.InstanceInfo
|
import net.corda.networkbuilder.containers.instance.InstanceInfo
|
||||||
import net.corda.networkbuilder.containers.instance.Instantiator
|
import net.corda.networkbuilder.containers.instance.Instantiator
|
||||||
import net.corda.networkbuilder.context.Context
|
import net.corda.networkbuilder.context.Context
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
class NodeInstantiator(val instantiator: Instantiator,
|
class NodeInstantiator(val instantiator: Instantiator,
|
||||||
|
@ -7,7 +7,6 @@ class CopiedNotary(configFile: File, baseDirectory: File,
|
|||||||
copiedNodeConfig: File, copiedNodeDir: File, val nodeInfoFile: File) :
|
copiedNodeConfig: File, copiedNodeDir: File, val nodeInfoFile: File) :
|
||||||
CopiedNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir)
|
CopiedNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir)
|
||||||
|
|
||||||
|
|
||||||
fun CopiedNode.toNotary(nodeInfoFile: File): CopiedNotary {
|
fun CopiedNode.toNotary(nodeInfoFile: File): CopiedNotary {
|
||||||
return CopiedNotary(this.configFile, this.baseDirectory, this.copiedNodeConfig, this.copiedNodeDir, nodeInfoFile)
|
return CopiedNotary(this.configFile, this.baseDirectory, this.copiedNodeConfig, this.copiedNodeDir, nodeInfoFile)
|
||||||
}
|
}
|
@ -2,11 +2,11 @@ package net.corda.networkbuilder.volumes
|
|||||||
|
|
||||||
import com.microsoft.azure.storage.file.CloudFile
|
import com.microsoft.azure.storage.file.CloudFile
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import net.corda.networkbuilder.notaries.CopiedNotary
|
|
||||||
import net.corda.networkbuilder.serialization.SerializationEngine
|
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.node.NotaryInfo
|
import net.corda.core.node.NotaryInfo
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
|
import net.corda.networkbuilder.notaries.CopiedNotary
|
||||||
|
import net.corda.networkbuilder.serialization.SerializationEngine
|
||||||
import net.corda.nodeapi.internal.DEV_ROOT_CA
|
import net.corda.nodeapi.internal.DEV_ROOT_CA
|
||||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||||
import net.corda.nodeapi.internal.config.getBooleanCaseInsensitive
|
import net.corda.nodeapi.internal.config.getBooleanCaseInsensitive
|
||||||
@ -28,7 +28,6 @@ interface Volume {
|
|||||||
internal val keyPair = networkMapCa.keyPair
|
internal val keyPair = networkMapCa.keyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun CloudFile.uploadFromByteArray(array: ByteArray) {
|
fun CloudFile.uploadFromByteArray(array: ByteArray) {
|
||||||
this.uploadFromByteArray(array, 0, array.size)
|
this.uploadFromByteArray(array, 0, array.size)
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,22 @@ import com.microsoft.azure.management.Azure
|
|||||||
import com.microsoft.azure.management.resources.ResourceGroup
|
import com.microsoft.azure.management.resources.ResourceGroup
|
||||||
import com.microsoft.azure.management.storage.StorageAccount
|
import com.microsoft.azure.management.storage.StorageAccount
|
||||||
import com.microsoft.azure.storage.CloudStorageAccount
|
import com.microsoft.azure.storage.CloudStorageAccount
|
||||||
|
import net.corda.core.internal.signWithCert
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.networkbuilder.Constants.Companion.restFriendlyName
|
import net.corda.networkbuilder.Constants.Companion.restFriendlyName
|
||||||
import net.corda.networkbuilder.notaries.CopiedNotary
|
import net.corda.networkbuilder.notaries.CopiedNotary
|
||||||
import net.corda.networkbuilder.volumes.Volume
|
import net.corda.networkbuilder.volumes.Volume
|
||||||
import net.corda.networkbuilder.volumes.Volume.Companion.keyPair
|
import net.corda.networkbuilder.volumes.Volume.Companion.keyPair
|
||||||
import net.corda.networkbuilder.volumes.Volume.Companion.networkMapCert
|
import net.corda.networkbuilder.volumes.Volume.Companion.networkMapCert
|
||||||
import net.corda.core.internal.signWithCert
|
|
||||||
import net.corda.core.serialization.serialize
|
|
||||||
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
|
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
|
||||||
class AzureSmbVolume(private val azure: Azure, private val resourceGroup: ResourceGroup) : Volume {
|
class AzureSmbVolume(private val azure: Azure, private val resourceGroup: ResourceGroup) : Volume {
|
||||||
|
|
||||||
private val storageAccount = getStorageAccount()
|
private val storageAccount = getStorageAccount()
|
||||||
|
|
||||||
private val accKeys = storageAccount.keys[0]
|
private val accKeys = storageAccount.keys[0]
|
||||||
|
|
||||||
|
|
||||||
private val cloudFileShare = CloudStorageAccount.parse(
|
private val cloudFileShare = CloudStorageAccount.parse(
|
||||||
"DefaultEndpointsProtocol=https;" +
|
"DefaultEndpointsProtocol=https;" +
|
||||||
"AccountName=${storageAccount.name()};" +
|
"AccountName=${storageAccount.name()};" +
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package net.corda.networkbuilder.volumes.docker
|
package net.corda.networkbuilder.volumes.docker
|
||||||
|
|
||||||
|
import net.corda.core.internal.signWithCert
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.networkbuilder.context.Context
|
import net.corda.networkbuilder.context.Context
|
||||||
import net.corda.networkbuilder.notaries.CopiedNotary
|
import net.corda.networkbuilder.notaries.CopiedNotary
|
||||||
import net.corda.networkbuilder.volumes.Volume
|
import net.corda.networkbuilder.volumes.Volume
|
||||||
import net.corda.core.internal.signWithCert
|
|
||||||
import net.corda.core.serialization.serialize
|
|
||||||
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
|
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -20,7 +20,8 @@ class LocalVolume(scratchDir: File, context: Context) : Volume {
|
|||||||
networkParamsDir.mkdirs()
|
networkParamsDir.mkdirs()
|
||||||
val networkParameters = convertNodeIntoToNetworkParams(notaries.map { it.configFile to it.nodeInfoFile })
|
val networkParameters = convertNodeIntoToNetworkParams(notaries.map { it.configFile to it.nodeInfoFile })
|
||||||
val networkParamsFile = File(networkParamsDir, NETWORK_PARAMS_FILE_NAME)
|
val networkParamsFile = File(networkParamsDir, NETWORK_PARAMS_FILE_NAME)
|
||||||
networkParamsFile.outputStream().use { networkParameters.signWithCert(Volume.keyPair.private, Volume.networkMapCert).serialize().writeTo(it) }
|
networkParamsFile.outputStream()
|
||||||
|
.use { networkParameters.signWithCert(Volume.keyPair.private, Volume.networkMapCert).serialize().writeTo(it) }
|
||||||
LOG.info("wrote network params to local file: ${networkParamsFile.absolutePath}")
|
LOG.info("wrote network params to local file: ${networkParamsFile.absolutePath}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@ import net.corda.tools.shell.utlities.CRaSHANSIProgressRenderer
|
|||||||
import org.apache.commons.lang3.SystemUtils
|
import org.apache.commons.lang3.SystemUtils
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.crsh.text.RenderPrintWriter
|
import org.crsh.text.RenderPrintWriter
|
||||||
import org.junit.Test
|
|
||||||
import rx.Observable
|
|
||||||
import org.fusesource.jansi.Ansi
|
import org.fusesource.jansi.Ansi
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
|
|
||||||
class ANSIProgressRendererTest {
|
class ANSIProgressRendererTest {
|
||||||
|
Loading…
Reference in New Issue
Block a user