Merge pull request #552 from corda/shams-nms-version-check

Introducing Platform Version and its use by the NMS for min version r…
This commit is contained in:
Shams Asari 2017-04-24 16:30:40 +01:00 committed by GitHub
commit af7f5ef0d7
35 changed files with 247 additions and 237 deletions

View File

@ -4,7 +4,10 @@ buildscript {
file("$projectDir/constants.properties").withInputStream { constants.load(it) }
// Our version: bump this on release.
ext.corda_version = "0.11-SNAPSHOT"
ext.corda_release_version = "0.11-SNAPSHOT"
// Increment this on any release that changes public APIs anywhere in the Corda platform
// TODO This is going to be difficult until we have a clear separation throughout the code of what is public and what is internal
ext.corda_platform_version = 1
ext.gradle_plugins_version = constants.getProperty("gradlePluginsVersion")
// Dependency versions. Can run 'gradle dependencyUpdates' to find new versions of things.
@ -105,8 +108,17 @@ allprojects {
}
}
tasks.withType(Jar) { // Includes War and Ear
manifest {
attributes('Corda-Release-Version': corda_release_version)
attributes('Corda-Platform-Version': corda_platform_version)
attributes('Corda-Revision': corda_revision)
attributes('Corda-Vendor': 'Corda Open Source')
}
}
group 'net.corda'
version "$corda_version"
version "$corda_release_version"
repositories {
mavenLocal()

View File

@ -1,4 +1,4 @@
gradlePluginsVersion=0.11.0
gradlePluginsVersion=0.11.1
kotlinVersion=1.1.1
guavaVersion=21.0
typesafeConfigVersion=1.3.1

View File

@ -50,6 +50,12 @@ sealed class StateMachineUpdate {
// TODO: The use of Pairs throughout is unfriendly for Java interop.
interface CordaRPCOps : RPCOps {
/**
* Returns the RPC protocol version, which is the same the node's Platform Version. Exists since version 1 so guaranteed
* to be present.
*/
override val protocolVersion: Int get() = nodeIdentity().platformVersion
/**
* Returns a pair of currently in-progress state machine infos and an observable of future state machine adds/removes.
*/

View File

@ -19,7 +19,7 @@ data class ServiceEntry(val info: ServiceInfo, val identity: Party)
@CordaSerializable
data class NodeInfo(val address: SingleMessageRecipient,
val legalIdentity: Party,
val version: Version,
val platformVersion: Int,
var advertisedServices: List<ServiceEntry> = emptyList(),
val physicalLocation: PhysicalLocation? = null) {
init {

View File

@ -1,35 +0,0 @@
package net.corda.core.node
import net.corda.core.serialization.CordaSerializable
import java.util.regex.Pattern
/**
* Versions of the same [major] version but with different [minor] versions are considered compatible with each other. One
* exception to this is when the major version is 0 - each different minor version should be considered incompatible.
*
* If two [Version]s are equal (i.e. [equals] returns true) but they are both [snapshot] then they may refer to different
* builds of the node. [NodeVersionInfo.revision] would be required to differentiate the two.
*/
@CordaSerializable
data class Version(val major: Int, val minor: Int, val patch: Int?, val snapshot: Boolean) {
companion object {
private val pattern = Pattern.compile("""(\d+)\.(\d+)(.(\d+))?(-SNAPSHOT)?""")
fun parse(string: String): Version {
val matcher = pattern.matcher(string)
require(matcher.matches())
val patch = matcher.group(4)?.toInt()
return Version(matcher.group(1).toInt(), matcher.group(2).toInt(), patch, matcher.group(5) != null)
}
}
override fun toString(): String {
val sb = StringBuilder()
sb.append(major, ".", minor)
if(patch != null) sb.append(".", patch)
if(snapshot) sb.append("-SNAPSHOT")
return sb.toString()
}
}
data class NodeVersionInfo(val version: Version, val revision: String, val vendor: String)

View File

@ -0,0 +1,17 @@
package net.corda.core.node
/**
* Encapsulates various pieces of version information of the node.
*/
data class VersionInfo(
/**
* Platform version of the node which is an integer value which increments on any release where any of the public
* API of the entire Corda platform changes. This includes messaging, serialisation, node APIs, etc.
*/
val platformVersion: Int,
/** Release version string of the node. */
val releaseVersion: String,
/** The exact version control commit ID of the node build. */
val revision: String,
/** The node vendor */
val vendor: String)

View File

@ -1,41 +0,0 @@
package net.corda.core.node
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Test
class VersionTest {
@Test
fun `parse valid non-SNAPSHOT string`() {
assertThat(Version.parse("1.2")).isEqualTo(Version(1, 2, null, false))
}
@Test
fun `parse valid SNAPSHOT string`() {
assertThat(Version.parse("2.23-SNAPSHOT")).isEqualTo(Version(2, 23, null, true))
}
@Test
fun `parse string with just major number`() {
assertThatThrownBy {
Version.parse("2")
}.isInstanceOf(IllegalArgumentException::class.java)
}
@Test
fun `parse string with unknown qualifier`() {
assertThatThrownBy {
Version.parse("2.3-TEST")
}.isInstanceOf(IllegalArgumentException::class.java)
}
@Test
fun `parses patch version`() {
assertThat(Version.parse("0.1.2")).isEqualTo(Version(0, 1, 2, false))
}
@Test
fun `parses snapshot patch version`() {
assertThat(Version.parse("0.1.2-SNAPSHOT")).isEqualTo(Version(0, 1, 2, true))
}
}

View File

@ -57,11 +57,11 @@ the ``cancel`` method on the future will unsubscribe it from any future value an
Versioning
----------
The client RPC protocol is versioned with a simple incrementing integer. When a proxy is created the server is
queried for its protocol version, and you can specify your minimum requirement. Methods added in later versions
are tagged with the ``@RPCSinceVersion`` annotation. If you try to use a method that the server isn't advertising
support of, an ``UnsupportedOperationException`` is thrown. If you want to know the version of the server, just
use the ``protocolVersion`` property (i.e. ``getProtocolVersion`` in Java).
The client RPC protocol is versioned using the node's Platform Version (see :doc:`versioning`). When a proxy is created
the server is queried for its version, and you can specify your minimum requirement. Methods added in later versions
are tagged with the ``@RPCSinceVersion`` annotation. If you try to use a method that the server isn't advertising support
of, an ``UnsupportedOperationException`` is thrown. If you want to know the version of the server, just use the
``protocolVersion`` property (i.e. ``getProtocolVersion`` in Java).
Thread safety
-------------

View File

@ -116,6 +116,10 @@ path to the node's base directory.
:legalName: Legal name of the node. This is required as part of the TLS host verification process. The node will
reject the connection to the network map service if it provides a TLS common name which doesn't match with this value.
:minimumPlatformVersion: Used by the node if it's running the network map service to enforce a minimum version requirement
on registrations - any node on a Platform Version lower than this value will have their registration rejected.
Defaults to 1 if absent.
:useHTTPS: If false the node's web server will be plain HTTP. If true the node will use the same certificate and private
key from the ``<workspace>/certificates/sslkeystore.jks`` file as the ArtemisMQ port for HTTPS. If HTTPS is enabled
then unencrypted HTTP traffic to the node's **webAddress** port is not supported.

View File

@ -128,8 +128,8 @@ the following segments to the relevant part of your build.gradle.
.. code-block:: groovy
buildscript {
ext.corda_version = '<enter the corda version you build against here>'
ext.corda_gradle_plugins_version = '<enter the gradle plugins version here>' // This is usually the same as corda_version.
ext.corda_release_version = '<enter the corda version you build against here>'
ext.corda_gradle_plugins_version = '<enter the gradle plugins version here>' // This is usually the same as corda_release_version.
... your buildscript ...
repositories {
@ -155,10 +155,10 @@ the following segments to the relevant part of your build.gradle.
}
dependencies {
compile "net.corda.core:$corda_version"
compile "net.corda.finance:$corda_version"
compile "net.corda.node:$corda_version"
compile "net.corda.corda:$corda_version"
compile "net.corda.core:$corda_release_version"
compile "net.corda.finance:$corda_release_version"
compile "net.corda.node:$corda_release_version"
compile "net.corda.corda:$corda_release_version"
... other dependencies here ...
}

View File

@ -72,6 +72,7 @@ Documentation Contents:
:maxdepth: 2
:caption: The Corda node
versioning
shell
serialization
clientrpc

View File

@ -22,12 +22,21 @@ X.500 distinguished names (see RFC 1779 for details on the construction of disti
* If you are using mock parties for testing, try to standardise on the ``DUMMY_NOTARY``, ``DUMMY_BANK_A``, etc. provided
in order to ensure consistency.
We have updated DemoBench so that it is installed as "Corda DemoBench" for both Windows and MacOSX. The original version was installed as just "DemoBench", and so will not be overwritten automatically by the new version.
We have updated DemoBench so that it is installed as "Corda DemoBench" for both Windows and MacOSX. The original version
was installed as just "DemoBench", and so will not be overwritten automatically by the new version.
We've introduced the concept of platform version which is a single integer value which increments by 1 if a release changes
any of the public APIs of the entire Corda platform. This includes the node's public APIs, the messaging protocol,
serialisation, etc. The node exposes the platform version it's on and we envision CorDapps will use this to be able to
run on older versions of the platform to the one they were compiled against. Platform version borrows heavily from Android's
API Level.
Milestone 10
------------
Special thank you to `Qian Hong <https://github.com/fracting>`_, `Marek Skocovsky <https://github.com/marekdapps>`_, `Karel Hajek <https://github.com/polybioz>`_, and `Jonny Chiu <https://github.com/johnnyychiu>`_ for their contributions to Corda in M10.
Special thank you to `Qian Hong <https://github.com/fracting>`_, `Marek Skocovsky <https://github.com/marekdapps>`_,
`Karel Hajek <https://github.com/polybioz>`_, and `Jonny Chiu <https://github.com/johnnyychiu>`_ for their contributions
to Corda in M10.
A new interactive **Corda Shell** has been added to the node. The shell lets developers and node administrators
easily command the node by running flows, RPCs and SQL queries. It also provides a variety of commands to monitor
@ -35,25 +44,34 @@ the node. The Corda Shell is based on the popular `CRaSH project <http://www.cra
be easily added to the node by simply dropping Groovy or Java files into the node's ``shell-commands`` directory.
We have many enhancements planned over time including SSH access, more commands and better tab completion.
The new "DemoBench" makes it easy to configure and launch local Corda nodes. It is a standalone desktop app that can be bundled with its own JRE and packaged as either EXE (Windows), DMG (MacOS) or RPM (Linux-based). It has the following features:
#. New nodes can be added at the click of a button. Clicking "Add node" creates a new tab that lets you edit the most important configuration properties of the node before launch, such as its legal name and which CorDapps will be loaded.
The new "DemoBench" makes it easy to configure and launch local Corda nodes. It is a standalone desktop app that can be
bundled with its own JRE and packaged as either EXE (Windows), DMG (MacOS) or RPM (Linux-based). It has the following
features:
#. New nodes can be added at the click of a button. Clicking "Add node" creates a new tab that lets you edit the most
important configuration properties of the node before launch, such as its legal name and which CorDapps will be loaded.
#. Each tab contains a terminal emulator, attached to the pseudoterminal of the node. This lets you see console output.
#. You can launch an Corda Explorer instance for each node at the click of a button. Credentials are handed to the Corda Explorer so it starts out logged in already.
#. You can launch an Corda Explorer instance for each node at the click of a button. Credentials are handed to the Corda
Explorer so it starts out logged in already.
#. Some basic statistics are shown about each node, informed via the RPC connection.
#. Another button launches a database viewer in the system browser.
#. The configurations of all running nodes can be saved into a single ``.profile`` file that can be reloaded later.
Soft Locking is a new feature implemented in the vault to prevent a node constructing transactions that attempt to use the same input(s) simultaneously.
Such transactions would result in naturally wasted effort when the notary rejects them as double spend attempts.
Soft locks are automatically applied to coin selection (eg. cash spending) to ensure that no two transactions attempt to spend the same fungible states.
Soft Locking is a new feature implemented in the vault to prevent a node constructing transactions that attempt to use the
same input(s) simultaneously. Such transactions would result in naturally wasted effort when the notary rejects them as
double spend attempts. Soft locks are automatically applied to coin selection (eg. cash spending) to ensure that no two
transactions attempt to spend the same fungible states.
The basic Amount API has been upgraded to have support for advanced financial use cases and to better integrate with currency reference data.
The basic Amount API has been upgraded to have support for advanced financial use cases and to better integrate with
currency reference data.
We have added optional out-of-process transaction verification. Any number of external verifier processes may be attached to the node which can handle loadbalanced verification requests.
We have added optional out-of-process transaction verification. Any number of external verifier processes may be attached
to the node which can handle loadbalanced verification requests.
We have also delivered the long waited Kotlin 1.1 upgrade in M10! The new features in Kotlin allow us to write even more clean and easy to manage code, which greatly increases our productivity.
We have also delivered the long waited Kotlin 1.1 upgrade in M10! The new features in Kotlin allow us to write even more
clean and easy to manage code, which greatly increases our productivity.
This release contains a large number of improvements, new features, library upgrades and bug fixes. For a full list of changes please see :doc:`changelog`.
This release contains a large number of improvements, new features, library upgrades and bug fixes. For a full list of
changes please see :doc:`changelog`.
Milestone 9
-----------

View File

@ -53,8 +53,8 @@ for you from our `public Maven repository <https://bintray.com/r3/corda>`_.
**Using a Corda SNAPSHOT build.** Alternatively, if you wish to work from the master branch of the Corda repo which contains
the most up-to-date Corda feature set then you will need to clone the ``corda`` repository and publish the latest master
build (or previously tagged releases) to your local Maven repository. You will then need to ensure that Gradle
grabs the correct dependencies for you from Maven local by changing the ``corda_version`` in ``build.gradle``. This will be
covered below in `Using a SNAPSHOT release`_.
grabs the correct dependencies for you from Maven local by changing the ``corda_release_version`` in ``build.gradle``.
This will be covered below in `Using a SNAPSHOT release`_.
Firstly, follow the :doc:`getting set up <getting-set-up>` page to download the JDK, IntelliJ and git if you didn't
already have it.
@ -145,10 +145,10 @@ if you are trying out new features, in this case you can change ``version`` for
.. note:: **A quick point on corda version numbers used by Gradle.**
In the ``build.gradle`` file for your CorDapp, you can specify the ``corda_version`` to use. It is important that when
developing your CorDapp that you use the correct version number. For example, when wanting to work from a SNAPSHOT
In the ``build.gradle`` file for your CorDapp, you can specify the ``corda_release_version`` to use. It is important
that when developing your CorDapp that you use the correct version number. For example, when wanting to work from a SNAPSHOT
release, the release numbers are suffixed with 'SNAPSHOT', e.g. if the latest milestone release is M6 then the
SNAPSHOT release will be 0.7-SNAPSHOT, and so on. As such, you will set your ``corda_version`` to ``'0.7-SNAPSHOT'``
SNAPSHOT release will be 0.7-SNAPSHOT, and so on. As such, you will set your ``corda_release_version`` to ``'0.7-SNAPSHOT'``
in the ``build.gradle`` file in your CorDapp. Gradle will automatically grab the SNAPSHOT dependencies from your local
Maven repository. Alternatively, if working from a milestone release, you will use the version number only, for example
``0.6`` or ``0.7``.
@ -224,7 +224,7 @@ see all available Gradle tasks.
* For the Corda repo there will be many project listed, the root project ``corda`` and associated sub-projects: ``core``,
``finance``, ``node``, etc.
.. note:: It's worth noting that when you change branch in the example CorDapp, the ``corda_version`` will change to
.. note:: It's worth noting that when you change branch in the example CorDapp, the ``corda_release_version`` will change to
reflect the version of the branch you are working from.
To execute a task, double click it. The output will be shown in a console window.
@ -712,15 +712,15 @@ are available for use in the rest of the build script. It also specifies version
things.
If you are working from a Corda SNAPSHOT release which you have publish to Maven local then ensure that
``corda_version`` is the same as the version of the Corda core modules you published to Maven local. If not then change the
``kotlin_version`` property. Also, if you are working from a previous cordapp-tutorial milestone release, then be sure to ``git checkout``
the correct version of the example CorDapp from the ``cordapp-tutorial`` repo.
``corda_release_version`` is the same as the version of the Corda core modules you published to Maven local. If not then
change the ``kotlin_version`` property. Also, if you are working from a previous cordapp-tutorial milestone release, then
be sure to ``git checkout`` the correct version of the example CorDapp from the ``cordapp-tutorial`` repo.
.. sourcecode:: groovy
buildscript {
ext.kotlin_version = '1.0.4'
ext.corda_version = '0.5-SNAPSHOT' // Ensure this version is the same as the corda core modules you are using.
ext.corda_release_version = '0.5-SNAPSHOT' // Ensure this version is the same as the corda core modules you are using.
ext.quasar_version = '0.7.6'
ext.jersey_version = '2.23.1'
@ -747,12 +747,12 @@ code snippet.package. Use the standard format:
testCompile group: 'junit', name: 'junit', version: '4.11'
// Corda integration dependencies
compile "net.corda:client:$corda_version"
compile "net.corda:core:$corda_version"
compile "net.corda:contracts:$corda_version"
compile "net.corda:node:$corda_version"
compile "net.corda:corda:$corda_version"
compile "net.corda:test-utils:$corda_version"
compile "net.corda:client:$corda_release_version"
compile "net.corda:core:$corda_release_version"
compile "net.corda:contracts:$corda_release_version"
compile "net.corda:node:$corda_release_version"
compile "net.corda:corda:$corda_release_version"
compile "net.corda:test-utils:$corda_release_version"
...

View File

@ -0,0 +1,29 @@
Versioning
==========
As the Corda platform evolves and new features are added it becomes important to have a versioning system which allows
its users to easily compare versions and know what feature are available to them. Each Corda release uses the standard
semantic versioning scheme of ``major.minor.patch``. This is useful when making releases in the public domain but is not
friendly for a developer working on the platform. It first has to be parsed and then they have three separate segments on
which to determine API differences. The release version is still useful and every MQ message the node sends attaches it
to the ``release-version`` header property for debugging purposes.
Platform Version
----------------
It is much easier to use a single incrementing integer value to represent the API version of the Corda platform, which
is called the Platform Version. It is similar to Android's `API Level <https://developer.android.com/guide/topics/manifest/uses-sdk-element.html>`_.
It starts at 1 and will increment by exactly 1 for each release which changes any of the publicly exposed APIs in the
entire platform. This includes public APIs on the node itself, the RPC system, messaging, serialisation, etc. API backwards
compatibility will always be maintained, with the use of deprecation to migrate away from old APIs. In rare situations
APIs may have to be removed, for example due to security issues. There is no relationship between the Platform Version
and the release version - a change in the major, minor or patch values may or may not increase the Platform Version.
The Platform Version is part of the node's ``NodeInfo`` object, which is available from the ``ServiceHub``. This enables
a CorDapp to find out which version it's running on and determine whether a desired feature is available. When a node
registers with the Network Map Service it will use the node's Platform Version to enforce a minimum version requirement
for the network.
.. note:: A future release may introduce the concept of a target platform version, which would be similar to Android's
``targetSdkVersion``, and would provide a means of maintaining behavioural compatibility for the cases where the
platform's behaviour has changed.

View File

@ -274,10 +274,10 @@ class Node {
*/
private File verifyAndGetCordaJar() {
def maybeCordaJAR = project.configurations.runtime.filter {
it.toString().contains("corda-${project.corda_version}.jar")
it.toString().contains("corda-${project.corda_release_version}.jar")
}
if (maybeCordaJAR.size() == 0) {
throw new RuntimeException("No Corda Capsule JAR found. Have you deployed the Corda project to Maven? Looked for \"corda-${project.corda_version}.jar\"")
throw new RuntimeException("No Corda Capsule JAR found. Have you deployed the Corda project to Maven? Looked for \"corda-${project.corda_release_version}.jar\"")
} else {
def cordaJar = maybeCordaJAR.getSingleFile()
assert(cordaJar.isFile())
@ -292,10 +292,10 @@ class Node {
*/
private File verifyAndGetWebserverJar() {
def maybeJar = project.configurations.runtime.filter {
it.toString().contains("corda-webserver-${project.corda_version}.jar")
it.toString().contains("corda-webserver-${project.corda_release_version}.jar")
}
if (maybeJar.size() == 0) {
throw new RuntimeException("No Corda Webserver JAR found. Have you deployed the Corda project to Maven? Looked for \"corda-webserver-${project.corda_version}.jar\"")
throw new RuntimeException("No Corda Webserver JAR found. Have you deployed the Corda project to Maven? Looked for \"corda-webserver-${project.corda_release_version}.jar\"")
} else {
def jar = maybeJar.getSingleFile()
assert(jar.isFile())

View File

@ -38,12 +38,12 @@ dependencies {
task buildCordaJAR(type: FatCapsule) {
applicationClass 'net.corda.node.Corda'
archiveName "corda-${corda_version}.jar"
archiveName "corda-${corda_release_version}.jar"
applicationSource = files(project.tasks.findByName('jar'), '../build/classes/main/CordaCaplet.class', '../build/classes/main/CordaCaplet$1.class', 'config/dev/log4j2.xml')
from 'NOTICE' // Copy CDDL notice
capsuleManifest {
applicationVersion = corda_version
applicationVersion = corda_release_version
appClassPath = ["jolokia-agent-war-${project.rootProject.ext.jolokia_version}.war"]
javaAgents = ["quasar-core-${quasar_version}-jdk8.jar"]
systemProperties['visualvm.display.name'] = 'Corda'
@ -63,12 +63,6 @@ task buildCordaJAR(type: FatCapsule) {
// This lets you run the file like so: ./corda.jar
// Other than being slightly less typing, this has one big advantage: Ctrl-C works properly in the terminal.
reallyExecutable { trampolining() }
manifest {
attributes('Corda-Version': corda_version)
attributes('Corda-Revision': corda_revision)
attributes('Corda-Vendor': 'Corda Open Source')
}
}
artifacts {

View File

@ -15,7 +15,7 @@ import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.network.NetworkMapService.RegistrationRequest
import net.corda.node.services.network.NodeRegistration
import net.corda.node.utilities.AddOrRemove
import net.corda.testing.MOCK_VERSION
import net.corda.testing.MOCK_VERSION_INFO
import net.corda.testing.TestNodeConfiguration
import net.corda.testing.node.NodeBasedTest
import net.corda.testing.node.SimpleNode
@ -63,7 +63,7 @@ class P2PSecurityTest : NodeBasedTest() {
}
private fun SimpleNode.registerWithNetworkMap(registrationName: String): ListenableFuture<NetworkMapService.RegistrationResponse> {
val nodeInfo = NodeInfo(net.myAddress, Party(registrationName, identity.public), MOCK_VERSION)
val nodeInfo = NodeInfo(net.myAddress, Party(registrationName, identity.public), MOCK_VERSION_INFO.platformVersion)
val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
val request = RegistrationRequest(registration.toWire(identity.private), net.myAddress)
return net.sendRequest<NetworkMapService.RegistrationResponse>(NetworkMapService.REGISTER_TOPIC, request, networkMapNode.net.myAddress)

View File

@ -6,8 +6,7 @@ import com.jcabi.manifests.Manifests
import com.typesafe.config.ConfigException
import joptsimple.OptionException
import net.corda.core.*
import net.corda.core.node.NodeVersionInfo
import net.corda.core.node.Version
import net.corda.core.node.VersionInfo
import net.corda.core.utilities.Emoji
import net.corda.core.utilities.LogHelper.withLevel
import net.corda.node.internal.Node
@ -69,15 +68,17 @@ fun main(args: Array<String>) {
// Manifest properties are only available if running from the corda jar
fun manifestValue(name: String): String? = if (Manifests.exists(name)) Manifests.read(name) else null
val nodeVersionInfo = NodeVersionInfo(
manifestValue("Corda-Version")?.let { Version.parse(it) } ?: Version(0, 0, 0, false),
val versionInfo = VersionInfo(
manifestValue("Corda-Platform-Version")?.toInt() ?: 1,
manifestValue("Corda-Release-Version") ?: "Unknown",
manifestValue("Corda-Revision") ?: "Unknown",
manifestValue("Corda-Vendor") ?: "Unknown"
)
if (cmdlineOptions.isVersion) {
println("${nodeVersionInfo.vendor} ${nodeVersionInfo.version}")
println("Revision ${nodeVersionInfo.revision}")
println("${versionInfo.vendor} ${versionInfo.releaseVersion}")
println("Revision ${versionInfo.revision}")
println("Platform Version ${versionInfo.platformVersion}")
exitProcess(0)
}
@ -87,7 +88,7 @@ fun main(args: Array<String>) {
exitProcess(0)
}
drawBanner(nodeVersionInfo)
drawBanner(versionInfo)
val log = LoggerFactory.getLogger("Main")
printBasicNodeInfo("Logs can be found in", System.getProperty("log-path"))
@ -110,9 +111,10 @@ fun main(args: Array<String>) {
exitProcess(0)
}
log.info("Version: ${nodeVersionInfo.version}")
log.info("Vendor: ${nodeVersionInfo.vendor}")
log.info("Revision: ${nodeVersionInfo.revision}")
log.info("Vendor: ${versionInfo.vendor}")
log.info("Release: ${versionInfo.releaseVersion}")
log.info("Platform Version: ${versionInfo.platformVersion}")
log.info("Revision: ${versionInfo.revision}")
val info = ManagementFactory.getRuntimeMXBean()
log.info("PID: ${info.name.split("@").firstOrNull()}") // TODO Java 9 has better support for this
log.info("Main class: ${FullNodeConfiguration::class.java.protectionDomain.codeSource.location.toURI().path}")
@ -132,7 +134,7 @@ fun main(args: Array<String>) {
try {
cmdlineOptions.baseDirectory.createDirectories()
val node = conf.createNode(nodeVersionInfo)
val node = conf.createNode(versionInfo)
node.start()
printPluginsAndServices(node)
@ -236,7 +238,7 @@ private fun messageOfTheDay(): Pair<String, String> {
return Pair(a, b)
}
private fun drawBanner(nodeVersionInfo: NodeVersionInfo) {
private fun drawBanner(versionInfo: VersionInfo) {
// This line makes sure ANSI escapes work on Windows, where they aren't supported out of the box.
AnsiConsole.systemInstall()
@ -249,7 +251,7 @@ private fun drawBanner(nodeVersionInfo: NodeVersionInfo) {
/ / __ / ___/ __ / __ `/ """).fgBrightBlue().a(msg1).newline().fgBrightRed().a(
"/ /___ /_/ / / / /_/ / /_/ / ").fgBrightBlue().a(msg2).newline().fgBrightRed().a(
"""\____/ /_/ \__,_/\__,_/""").reset().newline().newline().fgBrightDefault().bold().
a("--- ${nodeVersionInfo.vendor} ${nodeVersionInfo.version} (${nodeVersionInfo.revision.take(7)}) -----------------------------------------------").
a("--- ${versionInfo.vendor} ${versionInfo.releaseVersion} (${versionInfo.revision.take(7)}) -----------------------------------------------").
newline().
newline().
a("${Emoji.books}New! ").reset().a("Training now available worldwide, see https://corda.net/corda-training/").

View File

@ -101,7 +101,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
protected abstract val log: Logger
protected abstract val networkMapAddress: SingleMessageRecipient?
protected abstract val version: Version
protected abstract val platformVersion: Int
// We will run as much stuff in this single thread as possible to keep the risk of thread safety bugs low during the
// low-performance prototyping period.
@ -296,7 +296,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeInfo(): NodeInfo {
val advertisedServiceEntries = makeServiceEntries()
val legalIdentity = obtainLegalIdentity()
return NodeInfo(net.myAddress, legalIdentity, version, advertisedServiceEntries, findMyLocation())
return NodeInfo(net.myAddress, legalIdentity, platformVersion, advertisedServiceEntries, findMyLocation())
}
/**
@ -445,7 +445,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
protected open fun makeKeyManagementService(): KeyManagementService = PersistentKeyManagementService(partyKeys)
open protected fun makeNetworkMapService() {
inNodeNetworkMapService = PersistentNetworkMapService(services)
inNodeNetworkMapService = PersistentNetworkMapService(services, configuration.minimumPlatformVersion)
}
open protected fun makeNotaryService(type: ServiceType, tokenizableServices: MutableList<Any>): NotaryService {

View File

@ -5,14 +5,15 @@ import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.SettableFuture
import net.corda.core.*
import net.corda.core.div
import net.corda.core.flatMap
import net.corda.core.messaging.RPCOps
import net.corda.core.node.NodeVersionInfo
import net.corda.core.node.ServiceHub
import net.corda.core.node.Version
import net.corda.core.node.VersionInfo
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.node.services.UniquenessProvider
import net.corda.core.success
import net.corda.core.utilities.loggerFor
import net.corda.node.printBasicNodeInfo
import net.corda.node.serialization.NodeClock
@ -48,14 +49,14 @@ import kotlin.concurrent.thread
*/
class Node(override val configuration: FullNodeConfiguration,
advertisedServices: Set<ServiceInfo>,
val nodeVersionInfo: NodeVersionInfo,
val versionInfo: VersionInfo,
clock: Clock = NodeClock()) : AbstractNode(configuration, advertisedServices, clock) {
companion object {
private val logger = loggerFor<Node>()
}
override val log: Logger get() = logger
override val version: Version get() = nodeVersionInfo.version
override val platformVersion: Int get() = versionInfo.platformVersion
override val networkMapAddress: NetworkMapAddress? get() = configuration.networkMapService?.address?.let(::NetworkMapAddress)
override fun makeTransactionVerifierService() = (net as NodeMessagingClient).verifierService
@ -108,32 +109,13 @@ class Node(override val configuration: FullNodeConfiguration,
private lateinit var userService: RPCUserService
init {
checkVersionUnchanged()
}
/**
* Abort starting the node if an existing deployment with a different version is detected in the base directory.
*/
private fun checkVersionUnchanged() {
val versionFile = configuration.baseDirectory / "version"
if (versionFile.exists()) {
val previousVersion = Version.parse(versionFile.readAllLines()[0])
check(nodeVersionInfo.version.major == previousVersion.major) {
"Major version change detected - current: ${nodeVersionInfo.version}, previous: $previousVersion. " +
"Node upgrades across major versions are not yet supported."
}
}
versionFile.writeLines(listOf(nodeVersionInfo.version.toString()))
}
override fun makeMessagingService(): MessagingServiceInternal {
userService = RPCUserServiceImpl(configuration.rpcUsers)
val serverAddress = configuration.messagingServerAddress ?: makeLocalMessageBroker()
val myIdentityOrNullIfNetworkMapService = if (networkMapAddress != null) obtainLegalIdentity().owningKey else null
return NodeMessagingClient(
configuration,
nodeVersionInfo,
versionInfo,
serverAddress,
myIdentityOrNullIfNetworkMapService,
serverThread,

View File

@ -2,7 +2,7 @@ package net.corda.node.services.config
import com.google.common.net.HostAndPort
import net.corda.core.div
import net.corda.core.node.NodeVersionInfo
import net.corda.core.node.VersionInfo
import net.corda.core.node.services.ServiceInfo
import net.corda.node.internal.NetworkMapInfo
import net.corda.node.internal.Node
@ -22,6 +22,7 @@ interface NodeConfiguration : SSLConfiguration {
override val certificatesDirectory: Path get() = baseDirectory / "certificates"
val myLegalName: String
val networkMapService: NetworkMapInfo?
val minimumPlatformVersion: Int
val nearestCity: String
val emailAddress: String
val exportJMXto: String
@ -47,6 +48,7 @@ data class FullNodeConfiguration(
override val dataSourceProperties: Properties,
override val certificateSigningService: URL,
override val networkMapService: NetworkMapInfo?,
override val minimumPlatformVersion: Int = 1,
override val rpcUsers: List<User>,
override val verifierType: VerifierType,
val useHTTPS: Boolean,
@ -78,14 +80,14 @@ data class FullNodeConfiguration(
}
}
fun createNode(nodeVersionInfo: NodeVersionInfo): Node {
fun createNode(versionInfo: VersionInfo): Node {
val advertisedServices = extraAdvertisedServiceIds
.filter(String::isNotBlank)
.map { ServiceInfo.parse(it) }
.toMutableSet()
if (networkMapService == null) advertisedServices += ServiceInfo(NetworkMapService.type)
return Node(this, advertisedServices, nodeVersionInfo, if (useTestClock) TestClock() else NodeClock())
return Node(this, advertisedServices, versionInfo, if (useTestClock) TestClock() else NodeClock())
}
}

View File

@ -4,7 +4,7 @@ import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.ThreadBox
import net.corda.core.messaging.*
import net.corda.core.node.NodeVersionInfo
import net.corda.core.node.VersionInfo
import net.corda.core.node.services.PartyInfo
import net.corda.core.node.services.TransactionVerifierService
import net.corda.core.random63BitValue
@ -68,7 +68,7 @@ import java.security.PublicKey
*/
@ThreadSafe
class NodeMessagingClient(override val config: NodeConfiguration,
nodeVersionInfo: NodeVersionInfo,
val versionInfo: VersionInfo,
val serverHostPort: HostAndPort,
val myIdentity: PublicKey?,
val nodeExecutor: AffinityExecutor,
@ -85,9 +85,10 @@ class NodeMessagingClient(override val config: NodeConfiguration,
// confusion.
private val topicProperty = SimpleString("platform-topic")
private val sessionIdProperty = SimpleString("session-id")
private val nodeVersionProperty = SimpleString("node-version")
private val nodeVendorProperty = SimpleString("node-vendor")
private val amqDelay: Int = Integer.valueOf(System.getProperty("amq.delivery.delay.ms", "0"))
private val cordaVendorProperty = SimpleString("corda-vendor")
private val releaseVersionProperty = SimpleString("release-version")
private val platformVersionProperty = SimpleString("platform-version")
private val amqDelayMillis = System.getProperty("amq.delivery.delay.ms", "0").toInt()
private val verifierResponseAddress = "$VERIFICATION_RESPONSES_QUEUE_NAME_PREFIX.${random63BitValue()}"
}
@ -114,8 +115,8 @@ class NodeMessagingClient(override val config: NodeConfiguration,
data class Handler(val topicSession: TopicSession,
val callback: (ReceivedMessage, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration
private val nodeVendor = SimpleString(nodeVersionInfo.vendor)
private val version = SimpleString(nodeVersionInfo.version.toString())
private val cordaVendor = SimpleString(versionInfo.vendor)
private val releaseVersion = SimpleString(versionInfo.releaseVersion)
/** An executor for sending messages */
private val messagingExecutor = AffinityExecutor.ServiceAffinityExecutor("Messaging", 1)
@ -409,8 +410,9 @@ class NodeMessagingClient(override val config: NodeConfiguration,
state.locked {
val mqAddress = getMQAddress(target)
val artemisMessage = session!!.createMessage(true).apply {
putStringProperty(nodeVendorProperty, nodeVendor)
putStringProperty(nodeVersionProperty, version)
putStringProperty(cordaVendorProperty, cordaVendor)
putStringProperty(releaseVersionProperty, releaseVersion)
putIntProperty(platformVersionProperty, versionInfo.platformVersion)
putStringProperty(topicProperty, SimpleString(message.topicSession.topic))
putLongProperty(sessionIdProperty, message.topicSession.sessionID)
writeBodyBufferBytes(message.data)
@ -418,8 +420,8 @@ class NodeMessagingClient(override val config: NodeConfiguration,
putStringProperty(HDR_DUPLICATE_DETECTION_ID, SimpleString(message.uniqueMessageId.toString()))
// For demo purposes - if set then add a delay to messages in order to demonstrate that the flows are doing as intended
if (amqDelay > 0 && message.topicSession.topic == StateMachineManager.sessionTopic.topic) {
putLongProperty(HDR_SCHEDULED_DELIVERY_TIME, System.currentTimeMillis() + amqDelay)
if (amqDelayMillis > 0 && message.topicSession.topic == StateMachineManager.sessionTopic.topic) {
putLongProperty(HDR_SCHEDULED_DELIVERY_TIME, System.currentTimeMillis() + amqDelayMillis)
}
}
log.trace {

View File

@ -109,7 +109,8 @@ interface NetworkMapService {
}
@ThreadSafe
class InMemoryNetworkMapService(services: ServiceHubInternal) : AbstractNetworkMapService(services) {
class InMemoryNetworkMapService(services: ServiceHubInternal, minimumPlatformVersion: Int)
: AbstractNetworkMapService(services, minimumPlatformVersion) {
override val nodeRegistrations: MutableMap<Party, NodeRegistrationInfo> = ConcurrentHashMap()
override val subscribers = ThreadBox(mutableMapOf<SingleMessageRecipient, LastAcknowledgeInfo>())
@ -126,7 +127,8 @@ class InMemoryNetworkMapService(services: ServiceHubInternal) : AbstractNetworkM
* subscriber clean up and is simpler to persist than the previous implementation based on a set of missing messages acks.
*/
@ThreadSafe
abstract class AbstractNetworkMapService(services: ServiceHubInternal) : NetworkMapService, AbstractNodeService(services) {
abstract class AbstractNetworkMapService(services: ServiceHubInternal,
val minimumPlatformVersion: Int) : NetworkMapService, AbstractNodeService(services) {
companion object {
/**
* Maximum credible size for a registration request. Generally requests are around 500-600 bytes, so this gives a
@ -152,6 +154,13 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal) : Network
private val handlers = ArrayList<MessageHandlerRegistration>()
init {
require(minimumPlatformVersion >= 1) { "minimumPlatformVersion cannot be less than 1" }
require(minimumPlatformVersion <= services.myInfo.platformVersion) {
"minimumPlatformVersion cannot be greater than the node's own version"
}
}
protected fun setup() {
// Register message handlers
handlers += addMessageHandler(FETCH_TOPIC) { req: FetchMapRequest -> processFetchAllRequest(req) }
@ -219,7 +228,9 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal) : Network
}
private fun processRegistrationRequest(request: RegistrationRequest): RegistrationResponse {
if (request.wireReg.raw.size > MAX_SIZE_REGISTRATION_REQUEST_BYTES) return RegistrationResponse("Request is too big")
if (request.wireReg.raw.size > MAX_SIZE_REGISTRATION_REQUEST_BYTES) {
return RegistrationResponse("Request is too big")
}
val change = try {
request.wireReg.verified()
@ -229,11 +240,15 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal) : Network
val node = change.node
if (node.platformVersion < minimumPlatformVersion) {
return RegistrationResponse("Minimum platform version requirement not met: $minimumPlatformVersion")
}
// Update the current value atomically, so that if multiple updates come
// in on different threads, there is no risk of a race condition while checking
// sequence numbers.
val registrationInfo = try {
nodeRegistrations.compute(node.legalIdentity) { _: Party, existing: NodeRegistrationInfo? ->
nodeRegistrations.compute(node.legalIdentity) { _, existing: NodeRegistrationInfo? ->
require(!((existing == null || existing.reg.type == REMOVE) && change.type == REMOVE)) {
"Attempting to de-register unknown node"
}
@ -263,16 +278,16 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal) : Network
return RegistrationResponse(null)
}
private fun notifySubscribers(wireReg: WireNodeRegistration, mapVersion: Int) {
private fun notifySubscribers(wireReg: WireNodeRegistration, newMapVersion: Int) {
// TODO: Once we have a better established messaging system, we can probably send
// to a MessageRecipientGroup that nodes join/leave, rather than the network map
// service itself managing the group
val update = NetworkMapService.Update(wireReg, mapVersion, net.myAddress).serialize().bytes
val update = NetworkMapService.Update(wireReg, newMapVersion, net.myAddress).serialize().bytes
val message = net.createMessage(PUSH_TOPIC, DEFAULT_SESSION_ID, update)
subscribers.locked {
// Remove any stale subscribers
values.removeIf { lastAckInfo -> mapVersion - lastAckInfo.mapVersion > maxUnacknowledgedUpdates }
values.removeIf { (mapVersion) -> newMapVersion - mapVersion > maxUnacknowledgedUpdates }
// TODO: introduce some concept of time in the condition to avoid unsubscribes when there's a message burst.
keys.forEach { recipient -> net.send(message, recipient) }
}

View File

@ -17,7 +17,9 @@ import java.util.Collections.synchronizedMap
* This class needs database transactions to be in-flight during method calls and init, otherwise it will throw
* exceptions.
*/
class PersistentNetworkMapService(services: ServiceHubInternal) : AbstractNetworkMapService(services) {
class PersistentNetworkMapService(services: ServiceHubInternal, minimumPlatformVersion: Int)
: AbstractNetworkMapService(services, minimumPlatformVersion) {
private object Table : JDBCHashedTable("${NODE_DATABASE_PREFIX}network_map_nodes") {
val nodeParty = party("node_party_name", "node_party_key")
val registrationInfo = blob("node_registration_info")

View File

@ -25,7 +25,7 @@ import net.corda.node.services.transactions.PersistentUniquenessProvider
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
import net.corda.node.utilities.configureDatabase
import net.corda.node.utilities.transaction
import net.corda.testing.MOCK_NODE_VERSION_INFO
import net.corda.testing.MOCK_VERSION_INFO
import net.corda.testing.TestNodeConfiguration
import net.corda.testing.freeLocalHostAndPort
import net.corda.testing.node.makeTestDataSourceProperties
@ -225,7 +225,7 @@ class ArtemisMessagingTests {
return database.transaction {
NodeMessagingClient(
config,
MOCK_NODE_VERSION_INFO,
MOCK_VERSION_INFO,
server,
identity.public,
ServiceAffinityExecutor("ArtemisMessagingTests", 1),

View File

@ -5,6 +5,7 @@ import net.corda.core.node.services.ServiceInfo
import net.corda.node.services.api.ServiceHubInternal
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.utilities.transaction
import net.corda.testing.MOCK_VERSION_INFO
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode
import java.math.BigInteger
@ -48,11 +49,11 @@ class PersistentNetworkMapServiceTest : AbstractNetworkMapServiceTest<Persistent
* state within it is correctly restored.
*/
private class SwizzleNetworkMapService(val services: ServiceHubInternal) : NetworkMapService {
var delegate: PersistentNetworkMapService = PersistentNetworkMapService(services)
var delegate: PersistentNetworkMapService = PersistentNetworkMapService(services, MOCK_VERSION_INFO.platformVersion)
fun swizzle() {
delegate.unregisterNetworkHandlers()
delegate = PersistentNetworkMapService(services)
delegate = PersistentNetworkMapService(services, MOCK_VERSION_INFO.platformVersion)
}
}
}

View File

@ -6,11 +6,12 @@ package net.corda.testing
import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.contracts.StateRef
import net.corda.core.crypto.*
import net.corda.core.crypto.Party
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.generateKeyPair
import net.corda.core.flows.FlowLogic
import net.corda.core.node.NodeVersionInfo
import net.corda.core.node.ServiceHub
import net.corda.core.node.Version
import net.corda.core.node.VersionInfo
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.toFuture
import net.corda.core.transactions.TransactionBuilder
@ -83,8 +84,7 @@ val ALL_TEST_KEYS: List<KeyPair> get() = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, AL
val MOCK_IDENTITY_SERVICE: MockIdentityService get() = MockIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY))
val MOCK_VERSION = Version(0, 0, 0, false)
val MOCK_NODE_VERSION_INFO = NodeVersionInfo(MOCK_VERSION, "Mock revision", "Mock Vendor")
val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor")
fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0)
@ -156,6 +156,7 @@ data class TestNodeConfiguration(
override val baseDirectory: Path,
override val myLegalName: String,
override val networkMapService: NetworkMapInfo?,
override val minimumPlatformVersion: Int = 1,
override val keyStorePassword: String = "cordacadevpass",
override val trustStorePassword: String = "trustpass",
override val rpcUsers: List<User> = emptyList(),
@ -166,7 +167,8 @@ data class TestNodeConfiguration(
override val devMode: Boolean = true,
override val certificateSigningService: URL = URL("http://localhost"),
override val certificateChainCheckPolicies: List<CertChainPolicyConfig> = emptyList(),
override val verifierType: VerifierType = VerifierType.InMemory) : NodeConfiguration
override val verifierType: VerifierType = VerifierType.InMemory) : NodeConfiguration {
}
fun testConfiguration(baseDirectory: Path, legalName: String, basePort: Int): FullNodeConfiguration {
return FullNodeConfiguration(

View File

@ -7,7 +7,7 @@ import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache
import net.corda.node.services.network.InMemoryNetworkMapCache
import net.corda.testing.MOCK_VERSION
import net.corda.testing.MOCK_VERSION_INFO
import rx.Observable
import rx.subjects.PublishSubject
@ -20,8 +20,8 @@ class MockNetworkMapCache : InMemoryNetworkMapCache() {
data class MockAddress(val id: String) : SingleMessageRecipient
init {
val mockNodeA = NodeInfo(MockAddress("bankC:8080"), Party("Bank C", DummyPublicKey("Bank C")), MOCK_VERSION)
val mockNodeB = NodeInfo(MockAddress("bankD:8080"), Party("Bank D", DummyPublicKey("Bank D")), MOCK_VERSION)
val mockNodeA = NodeInfo(MockAddress("bankC:8080"), Party("Bank C", DummyPublicKey("Bank C")), MOCK_VERSION_INFO.platformVersion)
val mockNodeB = NodeInfo(MockAddress("bankD:8080"), Party("Bank D", DummyPublicKey("Bank D")), MOCK_VERSION_INFO.platformVersion)
registeredNodes[mockNodeA.legalIdentity.owningKey] = mockNodeA
registeredNodes[mockNodeB.legalIdentity.owningKey] = mockNodeB
runWithoutMapService()

View File

@ -12,7 +12,6 @@ import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.node.PhysicalLocation
import net.corda.core.node.ServiceEntry
import net.corda.core.node.Version
import net.corda.core.node.services.*
import net.corda.core.utilities.DUMMY_NOTARY_KEY
import net.corda.core.utilities.loggerFor
@ -29,7 +28,7 @@ import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.utilities.AffinityExecutor
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
import net.corda.testing.MOCK_VERSION
import net.corda.testing.MOCK_VERSION_INFO
import net.corda.testing.TestNodeConfiguration
import org.apache.activemq.artemis.utils.ReusableLatch
import org.slf4j.Logger
@ -136,7 +135,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
AbstractNode(config, advertisedServices, TestClock(), mockNet.busyLatch) {
var counter = entropyRoot
override val log: Logger = loggerFor<MockNode>()
override val version: Version get() = MOCK_VERSION
override val platformVersion: Int get() = MOCK_VERSION_INFO.platformVersion
override val serverThread: AffinityExecutor =
if (mockNet.threadPerNode)
ServiceAffinityExecutor("Mock node $id thread", 1)
@ -149,7 +148,15 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
// through the java.nio API which we are already mocking via Jimfs.
override fun makeMessagingService(): MessagingServiceInternal {
require(id >= 0) { "Node ID must be zero or positive, was passed: " + id }
return mockNet.messagingNetwork.createNodeWithID(!mockNet.threadPerNode, id, serverThread, makeServiceEntries(), configuration.myLegalName, database).start().getOrThrow()
return mockNet.messagingNetwork.createNodeWithID(
!mockNet.threadPerNode,
id,
serverThread,
makeServiceEntries(),
configuration.myLegalName,
database)
.start()
.getOrThrow()
}
override fun makeIdentityService() = MockIdentityService(mockNet.identities)
@ -165,7 +172,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
}
override fun makeNetworkMapService() {
inNodeNetworkMapService = InMemoryNetworkMapService(services)
inNodeNetworkMapService = InMemoryNetworkMapService(services, platformVersion)
}
override fun makeServiceEntries(): List<ServiceEntry> {

View File

@ -21,7 +21,7 @@ import net.corda.node.services.transactions.InMemoryTransactionVerifierService
import net.corda.node.services.vault.NodeVaultService
import net.corda.testing.MEGA_CORP
import net.corda.testing.MINI_CORP
import net.corda.testing.MOCK_VERSION
import net.corda.testing.MOCK_VERSION_INFO
import org.bouncycastle.asn1.x500.X500Name
import rx.Observable
import rx.subjects.PublishSubject
@ -68,7 +68,7 @@ open class MockServices(val key: KeyPair = generateKeyPair()) : ServiceHub {
override val networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException()
override val clock: Clock get() = Clock.systemUTC()
override val schedulerService: SchedulerService get() = throw UnsupportedOperationException()
override val myInfo: NodeInfo get() = NodeInfo(object : SingleMessageRecipient {}, Party("MegaCorp", key.public), MOCK_VERSION)
override val myInfo: NodeInfo get() = NodeInfo(object : SingleMessageRecipient {}, Party("MegaCorp", key.public), MOCK_VERSION_INFO.platformVersion)
override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService(2)
fun makeVaultService(dataSourceProps: Properties): VaultService {

View File

@ -16,7 +16,7 @@ import net.corda.node.services.transactions.RaftValidatingNotaryService
import net.corda.node.utilities.ServiceIdentityGenerator
import net.corda.nodeapi.User
import net.corda.nodeapi.config.parseAs
import net.corda.testing.MOCK_NODE_VERSION_INFO
import net.corda.testing.MOCK_VERSION_INFO
import net.corda.testing.getFreeLocalPorts
import org.apache.logging.log4j.Level
import org.junit.After
@ -141,7 +141,7 @@ abstract class NodeBasedTest {
) + configOverrides
)
val node = config.parseAs<FullNodeConfiguration>().createNode(MOCK_NODE_VERSION_INFO)
val node = config.parseAs<FullNodeConfiguration>().createNode(MOCK_VERSION_INFO)
node.start()
nodes += node
thread(name = legalName) {

View File

@ -5,6 +5,7 @@ import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.SettableFuture
import net.corda.core.crypto.generateKeyPair
import net.corda.core.messaging.RPCOps
import net.corda.testing.MOCK_VERSION_INFO
import net.corda.node.services.RPCUserServiceImpl
import net.corda.node.services.api.MonitoringService
import net.corda.node.services.config.NodeConfiguration
@ -13,7 +14,6 @@ import net.corda.node.services.messaging.NodeMessagingClient
import net.corda.node.services.network.InMemoryNetworkMapCache
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
import net.corda.node.utilities.configureDatabase
import net.corda.testing.MOCK_NODE_VERSION_INFO
import net.corda.node.utilities.transaction
import net.corda.testing.freeLocalHostAndPort
import org.jetbrains.exposed.sql.Database
@ -38,7 +38,7 @@ class SimpleNode(val config: NodeConfiguration, val address: HostAndPort = freeL
val net = database.transaction {
NodeMessagingClient(
config,
MOCK_NODE_VERSION_INFO,
MOCK_VERSION_INFO,
address,
identity.public,
executor,

View File

@ -80,7 +80,6 @@ dependencies {
jar {
manifest {
attributes(
'Corda-Version': corda_version,
'Main-Class': mainClassName,
'Class-Path': configurations.compile.collect { it.getName() }.join(' ')
)

View File

@ -31,12 +31,12 @@ dependencies {
task buildExplorerJAR(type: FatCapsule) {
applicationClass 'net.corda.explorer.Main'
archiveName "node-explorer-${corda_version}.jar"
archiveName "node-explorer-${corda_release_version}.jar"
applicationSource = files(project.tasks.findByName('jar'), '../build/classes/main/ExplorerCaplet.class')
classifier 'fat'
capsuleManifest {
applicationVersion = corda_version
applicationVersion = corda_release_version
systemProperties['visualvm.display.name'] = 'Node Explorer'
minJavaVersion = '1.8.0'
minUpdateVersion['1.8'] = java8_minUpdateVersion
@ -49,10 +49,6 @@ task buildExplorerJAR(type: FatCapsule) {
// If you change these flags, please also update Driver.kt
jvmArgs = ['-Xmx200m', '-XX:+UseG1GC']
}
manifest {
attributes('Corda-Version': corda_version)
}
}
build.dependsOn buildExplorerJAR

View File

@ -38,7 +38,7 @@ dependencies {
task buildWebserverJar(type: FatCapsule) {
applicationClass 'net.corda.webserver.WebServer'
archiveName "corda-webserver-${corda_version}.jar"
archiveName "corda-webserver-${corda_release_version}.jar"
applicationSource = files(
project.tasks.findByName('jar'),
new File(project(':node').rootDir, 'node/build/classes/main/CordaCaplet.class'),
@ -48,10 +48,9 @@ task buildWebserverJar(type: FatCapsule) {
from 'NOTICE' // Copy CDDL notice
capsuleManifest {
applicationVersion = corda_version
applicationVersion = corda_release_version
javaAgents = ["quasar-core-${quasar_version}-jdk8.jar"]
systemProperties['visualvm.display.name'] = 'Corda Webserver'
systemProperties['corda.version'] = corda_version
minJavaVersion = '1.8.0'
minUpdateVersion['1.8'] = java8_minUpdateVersion
caplets = ['CordaCaplet']
@ -63,10 +62,6 @@ task buildWebserverJar(type: FatCapsule) {
// If you change these flags, please also update Driver.kt
jvmArgs = ['-Xmx200m', '-XX:+UseG1GC']
}
manifest {
attributes('Corda-Version': corda_version)
}
}
artifacts {