mirror of
https://github.com/corda/corda.git
synced 2025-06-18 07:08:15 +00:00
CORDA-917 Bootstrap nodes without Notary schemas (by default) (#2376)
* Default jolokia version with optional override in CorDapp project gradle file. * Bootstrap a node without Notary schemas by default. * Revert unrelated Jolokia code change. * Revert unrelated Jolokia code change. * Addressed PR review feedback.
This commit is contained in:
@ -55,8 +55,7 @@ class Cordformation : Plugin<Project> {
|
|||||||
override fun apply(project: Project) {
|
override fun apply(project: Project) {
|
||||||
Utils.createCompileConfiguration("cordapp", project)
|
Utils.createCompileConfiguration("cordapp", project)
|
||||||
Utils.createRuntimeConfiguration(CORDFORMATION_TYPE, project)
|
Utils.createRuntimeConfiguration(CORDFORMATION_TYPE, project)
|
||||||
// TODO: improve how we re-use existing declared external variables from root gradle.build
|
val jolokiaVersion = project.rootProject.ext<String>("jolokia_version")
|
||||||
val jolokiaVersion = try { project.rootProject.ext<String>("jolokia_version") } catch (e: Exception) { "1.3.7" }
|
|
||||||
project.dependencies.add(CORDFORMATION_TYPE, "org.jolokia:jolokia-jvm:$jolokiaVersion:agent")
|
project.dependencies.add(CORDFORMATION_TYPE, "org.jolokia:jolokia-jvm:$jolokiaVersion:agent")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,8 +127,7 @@ class Node(private val project: Project) : CordformNode() {
|
|||||||
* Installs the jolokia monitoring agent JAR to the node/drivers directory
|
* Installs the jolokia monitoring agent JAR to the node/drivers directory
|
||||||
*/
|
*/
|
||||||
private fun installAgentJar() {
|
private fun installAgentJar() {
|
||||||
// TODO: improve how we re-use existing declared external variables from root gradle.build
|
val jolokiaVersion = project.rootProject.ext<String>("jolokia_version")
|
||||||
val jolokiaVersion = try { project.rootProject.ext<String>("jolokia_version") } catch (e: Exception) { "1.3.7" }
|
|
||||||
val agentJar = project.configuration("runtime").files {
|
val agentJar = project.configuration("runtime").files {
|
||||||
(it.group == "org.jolokia") &&
|
(it.group == "org.jolokia") &&
|
||||||
(it.name == "jolokia-jvm") &&
|
(it.name == "jolokia-jvm") &&
|
||||||
|
@ -205,7 +205,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
check(started == null) { "Node has already been started" }
|
check(started == null) { "Node has already been started" }
|
||||||
log.info("Node starting up ...")
|
log.info("Node starting up ...")
|
||||||
initCertificate()
|
initCertificate()
|
||||||
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas)
|
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas, configuration.notary != null)
|
||||||
val (identity, identityKeyPair) = obtainIdentity(notaryConfig = null)
|
val (identity, identityKeyPair) = obtainIdentity(notaryConfig = null)
|
||||||
val lh = lazyHub()
|
val lh = lazyHub()
|
||||||
configure(lh)
|
configure(lh)
|
||||||
|
@ -32,38 +32,44 @@ import net.corda.node.services.vault.VaultSchemaV1
|
|||||||
* TODO: support plugins for schema version upgrading or custom mapping not supported by original [QueryableState].
|
* TODO: support plugins for schema version upgrading or custom mapping not supported by original [QueryableState].
|
||||||
* TODO: create whitelisted tables when a CorDapp is first installed
|
* TODO: create whitelisted tables when a CorDapp is first installed
|
||||||
*/
|
*/
|
||||||
class NodeSchemaService(extraSchemas: Set<MappedSchema> = emptySet()) : SchemaService, SingletonSerializeAsToken() {
|
class NodeSchemaService(extraSchemas: Set<MappedSchema> = emptySet(), includeNotarySchemas: Boolean = false) : SchemaService, SingletonSerializeAsToken() {
|
||||||
// Entities for compulsory services
|
// Core Entities used by a Node
|
||||||
object NodeServices
|
object NodeCore
|
||||||
|
|
||||||
object NodeServicesV1 : MappedSchema(schemaFamily = NodeServices.javaClass, version = 1,
|
object NodeCoreV1 : MappedSchema(schemaFamily = NodeCore.javaClass, version = 1,
|
||||||
mappedTypes = listOf(DBCheckpointStorage.DBCheckpoint::class.java,
|
mappedTypes = listOf(DBCheckpointStorage.DBCheckpoint::class.java,
|
||||||
DBTransactionStorage.DBTransaction::class.java,
|
DBTransactionStorage.DBTransaction::class.java,
|
||||||
DBTransactionMappingStorage.DBTransactionMapping::class.java,
|
DBTransactionMappingStorage.DBTransactionMapping::class.java,
|
||||||
PersistentKeyManagementService.PersistentKey::class.java,
|
PersistentKeyManagementService.PersistentKey::class.java,
|
||||||
PersistentUniquenessProvider.PersistentUniqueness::class.java,
|
|
||||||
PersistentUniquenessProvider.PersistentNotaryCommit::class.java,
|
|
||||||
NodeSchedulerService.PersistentScheduledState::class.java,
|
NodeSchedulerService.PersistentScheduledState::class.java,
|
||||||
NodeAttachmentService.DBAttachment::class.java,
|
NodeAttachmentService.DBAttachment::class.java,
|
||||||
P2PMessagingClient.ProcessedMessage::class.java,
|
P2PMessagingClient.ProcessedMessage::class.java,
|
||||||
P2PMessagingClient.RetryMessage::class.java,
|
P2PMessagingClient.RetryMessage::class.java,
|
||||||
NodeAttachmentService.DBAttachment::class.java,
|
NodeAttachmentService.DBAttachment::class.java,
|
||||||
RaftUniquenessProvider.RaftState::class.java,
|
|
||||||
BFTNonValidatingNotaryService.PersistedCommittedState::class.java,
|
|
||||||
PersistentIdentityService.PersistentIdentity::class.java,
|
PersistentIdentityService.PersistentIdentity::class.java,
|
||||||
PersistentIdentityService.PersistentIdentityNames::class.java,
|
PersistentIdentityService.PersistentIdentityNames::class.java,
|
||||||
ContractUpgradeServiceImpl.DBContractUpgrade::class.java
|
ContractUpgradeServiceImpl.DBContractUpgrade::class.java
|
||||||
))
|
))
|
||||||
|
|
||||||
|
// Entities used by a Notary
|
||||||
|
object NodeNotary
|
||||||
|
|
||||||
|
object NodeNotaryV1 : MappedSchema(schemaFamily = NodeNotary.javaClass, version = 1,
|
||||||
|
mappedTypes = listOf(PersistentUniquenessProvider.PersistentUniqueness::class.java,
|
||||||
|
PersistentUniquenessProvider.PersistentNotaryCommit::class.java,
|
||||||
|
RaftUniquenessProvider.RaftState::class.java,
|
||||||
|
BFTNonValidatingNotaryService.PersistedCommittedState::class.java
|
||||||
|
))
|
||||||
|
|
||||||
// Required schemas are those used by internal Corda services
|
// Required schemas are those used by internal Corda services
|
||||||
// For example, cash is used by the vault for coin selection (but will be extracted as a standalone CorDapp in future)
|
|
||||||
private val requiredSchemas: Map<MappedSchema, SchemaService.SchemaOptions> =
|
private val requiredSchemas: Map<MappedSchema, SchemaService.SchemaOptions> =
|
||||||
mapOf(Pair(CommonSchemaV1, SchemaOptions()),
|
mapOf(Pair(CommonSchemaV1, SchemaOptions()),
|
||||||
Pair(VaultSchemaV1, SchemaOptions()),
|
Pair(VaultSchemaV1, SchemaOptions()),
|
||||||
Pair(NodeInfoSchemaV1, SchemaOptions()),
|
Pair(NodeInfoSchemaV1, SchemaOptions()),
|
||||||
Pair(NodeServicesV1, SchemaOptions()))
|
Pair(NodeCoreV1, SchemaOptions()))
|
||||||
|
private val notarySchemas = if (includeNotarySchemas) mapOf(Pair(NodeNotaryV1, SchemaOptions())) else emptyMap<MappedSchema, SchemaService.SchemaOptions>()
|
||||||
|
|
||||||
override val schemaOptions: Map<MappedSchema, SchemaService.SchemaOptions> = requiredSchemas + extraSchemas.associateBy({ it }, { SchemaOptions() })
|
override val schemaOptions: Map<MappedSchema, SchemaService.SchemaOptions> = requiredSchemas + notarySchemas + extraSchemas.associateBy({ it }, { SchemaOptions() })
|
||||||
|
|
||||||
// Currently returns all schemas supported by the state, with no filtering or enrichment.
|
// Currently returns all schemas supported by the state, with no filtering or enrichment.
|
||||||
override fun selectSchemas(state: ContractState): Iterable<MappedSchema> {
|
override fun selectSchemas(state: ContractState): Iterable<MappedSchema> {
|
||||||
|
@ -9,15 +9,19 @@ import net.corda.core.schemas.MappedSchema
|
|||||||
import net.corda.core.schemas.PersistentState
|
import net.corda.core.schemas.PersistentState
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.services.api.ServiceHubInternal
|
import net.corda.node.services.api.ServiceHubInternal
|
||||||
|
import net.corda.node.services.schema.NodeSchemaService.NodeCoreV1
|
||||||
|
import net.corda.node.services.schema.NodeSchemaService.NodeNotaryV1
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
|
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
|
||||||
|
import net.corda.testing.node.MockNetwork
|
||||||
import org.hibernate.annotations.Cascade
|
import org.hibernate.annotations.Cascade
|
||||||
import org.hibernate.annotations.CascadeType
|
import org.hibernate.annotations.CascadeType
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import javax.persistence.*
|
import javax.persistence.*
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class NodeSchemaServiceTest {
|
class NodeSchemaServiceTest {
|
||||||
@ -30,7 +34,30 @@ class NodeSchemaServiceTest {
|
|||||||
val mockNode = mockNet.createNode()
|
val mockNode = mockNet.createNode()
|
||||||
val schemaService = mockNode.services.schemaService
|
val schemaService = mockNode.services.schemaService
|
||||||
assertTrue(schemaService.schemaOptions.containsKey(DummyLinearStateSchemaV1))
|
assertTrue(schemaService.schemaOptions.containsKey(DummyLinearStateSchemaV1))
|
||||||
|
mockNet.stopNodes()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check node runs with minimal core schema set`() {
|
||||||
|
val mockNet = MockNetwork(cordappPackages = emptyList())
|
||||||
|
val mockNode = mockNet.createNode()
|
||||||
|
val schemaService = mockNode.services.schemaService
|
||||||
|
|
||||||
|
// check against NodeCore schemas
|
||||||
|
assertTrue(schemaService.schemaOptions.containsKey(NodeCoreV1))
|
||||||
|
assertFalse(schemaService.schemaOptions.containsKey(NodeNotaryV1))
|
||||||
|
mockNet.stopNodes()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check node runs inclusive of notary node schema set`() {
|
||||||
|
val mockNet = MockNetwork(cordappPackages = emptyList())
|
||||||
|
val mockNotaryNode = mockNet.notaryNodes.first()
|
||||||
|
val schemaService = mockNotaryNode.services.schemaService
|
||||||
|
|
||||||
|
// check against NodeCore + NodeNotary Schemas
|
||||||
|
assertTrue(schemaService.schemaOptions.containsKey(NodeCoreV1))
|
||||||
|
assertTrue(schemaService.schemaOptions.containsKey(NodeNotaryV1))
|
||||||
mockNet.stopNodes()
|
mockNet.stopNodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +86,34 @@ class NodeSchemaServiceTest {
|
|||||||
assertEquals<Set<*>>(expected, tables.toMutableSet().apply { retainAll(expected) })
|
assertEquals<Set<*>>(expected, tables.toMutableSet().apply { retainAll(expected) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
fun `check node runs with minimal core schema set using driverDSL`() {
|
||||||
|
// TODO: driver limitation: cannot restrict CorDapps that get automatically created by default,
|
||||||
|
// can ONLY specify additional ones using `extraCordappPackagesToScan` constructor argument.
|
||||||
|
driver(startNodesInProcess = true, notarySpecs = emptyList()) {
|
||||||
|
val node = startNode().getOrThrow()
|
||||||
|
val result = node.rpc.startFlow(::MappedSchemasFlow)
|
||||||
|
val mappedSchemas = result.returnValue.getOrThrow()
|
||||||
|
// check against NodeCore schemas
|
||||||
|
assertTrue(mappedSchemas.contains(NodeCoreV1.name))
|
||||||
|
assertFalse(mappedSchemas.contains(NodeNotaryV1.name)) // still gets loaded due TODO restriction
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check node runs inclusive of notary node schema set using driverDSL`() {
|
||||||
|
driver(startNodesInProcess = true) {
|
||||||
|
val notaryNode = defaultNotaryNode.getOrThrow().rpc.startFlow(::MappedSchemasFlow)
|
||||||
|
val mappedSchemas = notaryNode.returnValue.getOrThrow()
|
||||||
|
// check against NodeCore + NodeNotary Schemas
|
||||||
|
assertTrue(mappedSchemas.contains(NodeCoreV1.name))
|
||||||
|
assertTrue(mappedSchemas.contains(NodeNotaryV1.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@StartableByRPC
|
@StartableByRPC
|
||||||
class MappedSchemasFlow : FlowLogic<List<String>>() {
|
class MappedSchemasFlow : FlowLogic<List<String>>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
|
@ -11,6 +11,7 @@ import net.corda.core.internal.concurrent.transpose
|
|||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.configureDatabase
|
import net.corda.node.internal.configureDatabase
|
||||||
|
import net.corda.node.services.schema.NodeSchemaService
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||||
import net.corda.testing.internal.LogHelper
|
import net.corda.testing.internal.LogHelper
|
||||||
@ -88,7 +89,7 @@ class DistributedImmutableMapTests {
|
|||||||
private fun createReplica(myAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): CompletableFuture<Member> {
|
private fun createReplica(myAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): CompletableFuture<Member> {
|
||||||
val storage = Storage.builder().withStorageLevel(StorageLevel.MEMORY).build()
|
val storage = Storage.builder().withStorageLevel(StorageLevel.MEMORY).build()
|
||||||
val address = Address(myAddress.host, myAddress.port)
|
val address = Address(myAddress.host, myAddress.port)
|
||||||
val database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(serverNameTablePrefix = "PORT_${myAddress.port}_"), rigorousMock())
|
val database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(serverNameTablePrefix = "PORT_${myAddress.port}_"), rigorousMock(), NodeSchemaService(includeNotarySchemas = true))
|
||||||
databases.add(database)
|
databases.add(database)
|
||||||
val stateMachineFactory = { DistributedImmutableMap(database, RaftUniquenessProvider.Companion::createMap) }
|
val stateMachineFactory = { DistributedImmutableMap(database, RaftUniquenessProvider.Companion::createMap) }
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import net.corda.core.crypto.SecureHash
|
|||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.UniquenessException
|
import net.corda.core.node.services.UniquenessException
|
||||||
import net.corda.node.internal.configureDatabase
|
import net.corda.node.internal.configureDatabase
|
||||||
|
import net.corda.node.services.schema.NodeSchemaService
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
@ -29,7 +30,7 @@ class PersistentUniquenessProviderTests {
|
|||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
LogHelper.setLevel(PersistentUniquenessProvider::class)
|
LogHelper.setLevel(PersistentUniquenessProvider::class)
|
||||||
database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(), rigorousMock())
|
database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(), rigorousMock(), NodeSchemaService(includeNotarySchemas = true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
Reference in New Issue
Block a user