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:
josecoll 2018-01-18 10:10:06 +00:00 committed by GitHub
parent 619f333541
commit e699dad076
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 21 deletions

View File

@ -55,8 +55,7 @@ class Cordformation : Plugin<Project> {
override fun apply(project: Project) {
Utils.createCompileConfiguration("cordapp", project)
Utils.createRuntimeConfiguration(CORDFORMATION_TYPE, project)
// TODO: improve how we re-use existing declared external variables from root gradle.build
val jolokiaVersion = try { project.rootProject.ext<String>("jolokia_version") } catch (e: Exception) { "1.3.7" }
val jolokiaVersion = project.rootProject.ext<String>("jolokia_version")
project.dependencies.add(CORDFORMATION_TYPE, "org.jolokia:jolokia-jvm:$jolokiaVersion:agent")
}
}

View File

@ -127,8 +127,7 @@ class Node(private val project: Project) : CordformNode() {
* Installs the jolokia monitoring agent JAR to the node/drivers directory
*/
private fun installAgentJar() {
// TODO: improve how we re-use existing declared external variables from root gradle.build
val jolokiaVersion = try { project.rootProject.ext<String>("jolokia_version") } catch (e: Exception) { "1.3.7" }
val jolokiaVersion = project.rootProject.ext<String>("jolokia_version")
val agentJar = project.configuration("runtime").files {
(it.group == "org.jolokia") &&
(it.name == "jolokia-jvm") &&

View File

@ -205,7 +205,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
check(started == null) { "Node has already been started" }
log.info("Node starting up ...")
initCertificate()
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas)
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas, configuration.notary != null)
val (identity, identityKeyPair) = obtainIdentity(notaryConfig = null)
val lh = lazyHub()
configure(lh)

View File

@ -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: create whitelisted tables when a CorDapp is first installed
*/
class NodeSchemaService(extraSchemas: Set<MappedSchema> = emptySet()) : SchemaService, SingletonSerializeAsToken() {
// Entities for compulsory services
object NodeServices
class NodeSchemaService(extraSchemas: Set<MappedSchema> = emptySet(), includeNotarySchemas: Boolean = false) : SchemaService, SingletonSerializeAsToken() {
// Core Entities used by a Node
object NodeCore
object NodeServicesV1 : MappedSchema(schemaFamily = NodeServices.javaClass, version = 1,
object NodeCoreV1 : MappedSchema(schemaFamily = NodeCore.javaClass, version = 1,
mappedTypes = listOf(DBCheckpointStorage.DBCheckpoint::class.java,
DBTransactionStorage.DBTransaction::class.java,
DBTransactionMappingStorage.DBTransactionMapping::class.java,
PersistentKeyManagementService.PersistentKey::class.java,
PersistentUniquenessProvider.PersistentUniqueness::class.java,
PersistentUniquenessProvider.PersistentNotaryCommit::class.java,
NodeSchedulerService.PersistentScheduledState::class.java,
NodeAttachmentService.DBAttachment::class.java,
P2PMessagingClient.ProcessedMessage::class.java,
P2PMessagingClient.RetryMessage::class.java,
NodeAttachmentService.DBAttachment::class.java,
RaftUniquenessProvider.RaftState::class.java,
BFTNonValidatingNotaryService.PersistedCommittedState::class.java,
PersistentIdentityService.PersistentIdentity::class.java,
PersistentIdentityService.PersistentIdentityNames::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
// 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> =
mapOf(Pair(CommonSchemaV1, SchemaOptions()),
Pair(VaultSchemaV1, SchemaOptions()),
Pair(NodeInfoSchemaV1, SchemaOptions()),
Pair(NodeServicesV1, SchemaOptions()))
Pair(VaultSchemaV1, SchemaOptions()),
Pair(NodeInfoSchemaV1, 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.
override fun selectSchemas(state: ContractState): Iterable<MappedSchema> {

View File

@ -9,15 +9,19 @@ import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import net.corda.core.utilities.getOrThrow
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.driver
import net.corda.testing.node.MockNetwork
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
import net.corda.testing.node.MockNetwork
import org.hibernate.annotations.Cascade
import org.hibernate.annotations.CascadeType
import org.junit.Ignore
import org.junit.Test
import javax.persistence.*
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class NodeSchemaServiceTest {
@ -30,7 +34,30 @@ class NodeSchemaServiceTest {
val mockNode = mockNet.createNode()
val schemaService = mockNode.services.schemaService
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()
}
@ -59,6 +86,34 @@ class NodeSchemaServiceTest {
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
class MappedSchemasFlow : FlowLogic<List<String>>() {
@Suspendable

View File

@ -11,6 +11,7 @@ import net.corda.core.internal.concurrent.transpose
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.getOrThrow
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.DatabaseConfig
import net.corda.testing.internal.LogHelper
@ -88,7 +89,7 @@ class DistributedImmutableMapTests {
private fun createReplica(myAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): CompletableFuture<Member> {
val storage = Storage.builder().withStorageLevel(StorageLevel.MEMORY).build()
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)
val stateMachineFactory = { DistributedImmutableMap(database, RaftUniquenessProvider.Companion::createMap) }

View File

@ -4,6 +4,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.node.services.UniquenessException
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.DatabaseConfig
import net.corda.testing.*
@ -29,7 +30,7 @@ class PersistentUniquenessProviderTests {
@Before
fun setUp() {
LogHelper.setLevel(PersistentUniquenessProvider::class)
database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(), rigorousMock())
database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(), rigorousMock(), NodeSchemaService(includeNotarySchemas = true))
}
@After