Merge remote-tracking branch 'remotes/open/master' into mnesbit-merge-20180702

# Conflicts:
#	node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
This commit is contained in:
Matthew Nesbit 2018-07-02 11:31:18 +01:00
commit 0f98a1cbcd
21 changed files with 108 additions and 135 deletions

View File

@ -6328,7 +6328,7 @@ public class net.corda.testing.node.MockServices extends java.lang.Object implem
@NotNull
public final net.corda.testing.services.MockAttachmentStorage getAttachments()
@NotNull
public java.time.Clock getClock()
public net.corda.testing.node.TestClock getClock()
@NotNull
public net.corda.core.node.services.ContractUpgradeService getContractUpgradeService()
@NotNull

View File

@ -66,6 +66,7 @@ buildscript {
ext.jsr305_version = constants.getProperty("jsr305Version")
ext.spring_jdbc_version ='5.0.0.RELEASE'
ext.shiro_version = '1.4.0'
ext.shadow_version = '2.0.4'
ext.artifactory_plugin_version = constants.getProperty('artifactoryPluginVersion')
ext.liquibase_version = '3.5.3'
ext.shadow_version = '2.0.2'
@ -398,7 +399,7 @@ bintrayConfig {
'corda-confidential-identities',
'corda-launcher',
'corda-shell',
'corda-shell-cli',
'corda-tools-shell-cli',
'corda-serialization',
'corda-serialization-deterministic',
'corda-tools-blob-inspector',

View File

@ -15,7 +15,7 @@ import org.objectweb.asm.Opcodes.*
* This Visitor is applied to the byte-code repeatedly until it has removed
* everything that is no longer wanted.
*/
class ClassTransformer private constructor (
class FilterTransformer private constructor (
visitor: ClassVisitor,
logger: Logger,
kotlinMetadata: MutableMap<String, List<String>>,
@ -26,7 +26,7 @@ class ClassTransformer private constructor (
private val unwantedFields: MutableSet<FieldElement>,
private val deletedMethods: MutableSet<MethodElement>,
private val stubbedMethods: MutableSet<MethodElement>
) : KotlinAwareVisitor(ASM6, visitor, logger, kotlinMetadata), Repeatable<ClassTransformer> {
) : KotlinAwareVisitor(ASM6, visitor, logger, kotlinMetadata), Repeatable<FilterTransformer> {
constructor(
visitor: ClassVisitor,
logger: Logger,
@ -62,7 +62,7 @@ class ClassTransformer private constructor (
name.startsWith("$className\$${method.visibleName}\$")
}
override fun recreate(visitor: ClassVisitor) = ClassTransformer(
override fun recreate(visitor: ClassVisitor) = FilterTransformer(
visitor = visitor,
logger = logger,
kotlinMetadata = kotlinMetadata,

View File

@ -211,7 +211,7 @@ open class JarFilterTask : DefaultTask() {
private fun transform(inBytes: ByteArray): ByteArray {
var reader = ClassReader(inBytes)
var writer = ClassWriter(COMPUTE_MAXS)
var transformer = ClassTransformer(
var transformer = FilterTransformer(
visitor = writer,
logger = logger,
removeAnnotations = toDescriptors(forRemove),

View File

@ -19,7 +19,7 @@ import java.io.InputStream
/**
* Base class for removing unwanted elements from [kotlin.Metadata] annotations.
* This is used by [ClassTransformer] for [JarFilterTask].
* This is used by [FilterTransformer] for [JarFilterTask].
*/
internal abstract class MetadataTransformer<out T : MessageLite>(
private val logger: Logger,

View File

@ -46,7 +46,7 @@ class FieldRemovalTest {
private fun <T: R, R: Any> transform(type: Class<in T>, asType: Class<out R>): Class<out R> {
val bytecode = type.bytecode.execute({ writer ->
ClassTransformer(
FilterTransformer(
visitor = writer,
logger = logger,
removeAnnotations = emptySet(),

View File

@ -28,7 +28,7 @@ class StaticFieldRemovalTest {
private fun <T : R, R : Any> transform(type: Class<in T>, asType: Class<out R>): Class<out R> {
val bytecode = type.bytecode.execute({ writer ->
ClassTransformer(
FilterTransformer(
visitor = writer,
logger = logger,
removeAnnotations = emptySet(),

View File

@ -62,7 +62,7 @@ DemoBench writes a log file to the following location:
Building the Installers
-----------------------
Gradle defines tasks that build DemoBench installers using JavaPackager. There are three scripts in the ``tools/demobench`` directory to execute these tasks:
Gradle defines tasks that build DemoBench installers using JavaPackager. There are three scripts in the `tools/demobench <https://github.com/corda/corda/tree/master/tools/demobench>`_ directory of the `Corda repository <https://github.com/corda/corda>`_ to execute these tasks:
#. ``package-demobench-exe.bat`` (Windows)
#. ``package-demobench-dmg.sh`` (MacOS)

View File

@ -24,7 +24,7 @@ transaction gathers all the required signatures, it is only valid if it is also
**Contract validity** is defined as follows:
* Each state points to a *contract*
* Each transaction state specifies a *contract* type
* A *contract* takes a transaction as input, and states whether the transaction is considered valid based on the
contract's rules
* A transaction is only valid if the contract of **every input state** and **every output state** considers it to be
@ -56,12 +56,15 @@ given transaction. For example, transaction validity cannot depend on the time a
the amount of information the peer running the contract holds. This is a necessary condition to ensure that all peers
on the network reach consensus regarding the validity of a given ledger update.
To achieve this, contracts evaluate transactions in a deterministic sandbox. The sandbox has a whitelist that
Future versions of Corda will evaluate transactions in a strictly deterministic sandbox. The sandbox has a whitelist that
prevents the contract from importing libraries that could be a source of non-determinism. This includes libraries
that provide the current time, random number generators, libraries that provide filesystem access or networking
libraries, for example. Ultimately, the only information available to the contract when verifying the transaction is
the information included in the transaction itself.
Developers can pre-verify their CorDapps are determinsitic by linking their CorDapps against the deterministic modules
(see the :doc:`Deterministic Corda Modules <deterministic-modules>`).
Contract limitations
--------------------
Since a contract has no access to information from the outside world, it can only check the transaction for internal

View File

@ -10,13 +10,17 @@ Identity
Identities in Corda can represent:
* Legal identity of an organisation
* Service identity of a network service
* The legal identity of an organisation
* The service identity of a network service
Legal identities are used for parties in a transaction, such as the owner of a cash state. Service identities are used
for those providing transaction-related services, such as notary, or oracle. Service identities are distinct to legal
identities so that distributed services can exist on nodes owned by different organisations. Such distributed service
identities are based on ``CompositeKeys``, which describe the valid sets of signers for a signature from the service.
These identities are distinct from the RPC users that are able to connect to the node via RPC.
Identity types
--------------
Whereas legal identities are used to represent parties in transactions, such as the owner of a cash state, service identities
are used for entities providing transaction-related services, such as notaries or oracles. Service identities are distinct
from legal identities so that distributed services can exist on nodes owned by different organisations. Such distributed service identities are based on ``CompositeKeys``, which describe the valid sets of signers for a signature from the service.
See :doc:`api-core-types` for more technical detail on composite keys.
Identities are either well known or confidential, depending on whether their X.509 certificate (and corresponding
@ -55,4 +59,4 @@ business sensitive details of transactions). In some cases nodes may also use pr
to the main network map service, for operational reasons. Identities registered with such network maps must be
considered well known, and it is never appropriate to store confidential identities in a central directory without
controls applied at the record level to ensure only those who require access to an identity can retrieve its
certificate.
certificate.

View File

@ -63,8 +63,8 @@ is designed to make this possible by:
* Having permissioned networks, meaning that participants are aware of who they are dealing with in every single
transaction
* All code contracts are backed by a legal document describing the contract's intended behavior which can be relied
upon to resolve conflicts
* All code contracts should include a ``LegalProseReference`` link to the legal document describing the contract's intended behavior
which can be relied upon to resolve conflicts
Build vs. re-use
----------------

View File

@ -13,14 +13,15 @@ Every Corda node is a part of a network (also called a zone), and networks are *
zone, a node needs a signed X.509 certificate from the network operator. Production deployments require a secure certificate authority.
The issued certificates take the form of three keystores in a node's ``<workspace>/certificates/`` folder:
* ``network-root-truststore.jks``, which stores the network/zone operator's public keys and certificates
* ``network-root-truststore.jks``, the network/zone operator's public keys and certificates as provided by them with a standard password. Can be deleted after initial registration
* ``truststore.jks``, the network/zone operator's public keys and certificates in keystore with a locally configurable password as protection against certain attacks
* ``nodekeystore.jks``, which stores the nodes identity keypairs and certificates
* ``sslkeystore.jks``, which stores the nodes TLS keypairs and certificates
Most users will join an existing network such as the main Corda network or the Corda TestNet. You can also build your
own networks. During development, no network is required because you can use the included tools to pre-create
and pre-distribute the certificates and map files that would normally be provided dynamically by the network. Effectively
the bootstrapper tool creates a private semi-static network for you.
the :doc:`bootstrapper tool <network-bootstrapper>` creates a private semi-static network for you.
Certificate hierarchy
---------------------
@ -72,9 +73,8 @@ certificates must obey the following restrictions:
The required identity and TLS keys/certificates will be automatically generated for you by the node on first run.
However, you can also generate them manually for more control. The ``X509Utilities`` class shows how to generate the
required public/private keypairs and certificates using Bouncy Castle. You can find the ``X509Utilities`` in the `Corda
repository <https://github.com/corda/corda>`__, under
``/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt``.
required public/private keypairs and certificates using Bouncy Castle. You can find it in the `Corda repository
<https://github.com/corda/corda/blob/master/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt>`__.
Certificate role extension
--------------------------
@ -140,7 +140,7 @@ The following information from the node configuration file is needed to generate
* **devMode** must be set to false
* **networkServices or compatibilityZoneURL** The Corda compatibility zone services must be configured. This must be either:
* **networkServices** or **compatibilityZoneURL** The Corda compatibility zone services must be configured. This must be either:
* **compatibilityZoneURL** The Corda compatibility zone network management service root URL.
* **networkServices** Replaces the ``compatibilityZoneURL`` when the doorman and network map services
@ -172,7 +172,7 @@ Think twice before going down this route:
1. It isn't necessary for testing.
2. It isn't necessary for adding another layer of permissioning or 'know your customer' requirements onto your app.
**Testing.** Creating a production-ready zone isn't necessary for testing as you can use the *network bootstrapper*
**Testing.** Creating a production-ready zone isn't necessary for testing as you can use the :doc:`network bootstrapper <network-bootstrapper>`
tool to create all the certificates, keys, and distribute the needed map files to run many nodes. The bootstrapper can
create a network locally on your desktop/laptop but it also knows how to automate cloud providers via their APIs and
using Docker. In this way you can bring up a simulation of a real Corda network with different nodes on different
@ -277,8 +277,9 @@ Setting zone parameters
Zone parameters are stored in a file containing a Corda AMQP serialised ``SignedDataWithCert<NetworkParameters>``
object. It is easy to create such a file with a small Java or Kotlin program. The ``NetworkParameters`` object is a
simple data holder that could be read from e.g. a config file, or settings from a database. Signing and saving the
resulting file is just a few lines of code. A full example can be found in ``NetworkParametersCopier.kt`` in the source
tree, but a flavour of it looks like this:
resulting file is just a few lines of code. A full example can be found in `NetworkParametersCopier.kt
<https://github.com/corda/corda/blob/master/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkParametersCopier.kt>`__,
but a flavour of it looks like this:
.. container:: codeset

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View File

@ -108,7 +108,7 @@ Linux and MacOS
.. code:: bash
./shell [--config-file PATH | --cordpass-directory PATH --commands-directory PATH --host HOST --port PORT
java -jar corda-tools-shell-cli-VERSION_NUMBER.jar [--config-file PATH | --cordpass-directory PATH --commands-directory PATH --host HOST --port PORT
--user USER --password PASSWORD --sshd-port PORT --sshd-hostkey-directory PATH --keystore-password PASSWORD
--keystore-file FILE --truststore-password PASSWORD --truststore-file FILE | --help]
@ -117,7 +117,7 @@ Windows
.. code:: bash
shell.bat [--config-file PATH | --cordpass-directory PATH --commands-directory PATH --host HOST --port PORT
java -jar corda-tools-shell-cli-VERSION_NUMBER.jar [--config-file PATH | --cordpass-directory PATH --commands-directory PATH --host HOST --port PORT
--user USER --password PASSWORD --sshd-port PORT --sshd-hostkey-directory PATH --keystore-password PASSWORD
--keystore-file FILE --truststore-password PASSWORD --truststore-file FILE | --help]

View File

@ -50,7 +50,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.ExternalResource
import java.lang.Thread.sleep
import java.time.Duration
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
@ -208,7 +208,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
vaultFiller.fillWithSomeTestLinearStates(3, "ABC")
val dealStates = vaultFiller.fillWithSomeTestDeals(listOf("123", "456", "789"))
// Total unconsumed states = 10 + 1 + 2 + 3 + 3 = 19
sleep(delay)
services.clock.advanceBy(Duration.ofMillis(delay))
// consume some states
vaultFiller.consumeLinearStates(linearStatesXYZ.states.toList())
@ -1817,12 +1817,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
// specifying Query on Linear state attributes
@Test
fun `unconsumed linear heads for linearId between two timestamps`() {
val start = Instant.now()
val end = start.plus(1, ChronoUnit.SECONDS)
database.transaction {
val start = services.clock.instant()
vaultFiller.fillWithSomeTestLinearStates(1, "TEST")
sleep(1000)
services.clock.advanceBy(1.seconds)
val end = services.clock.instant()
vaultFiller.fillWithSomeTestLinearStates(1, "TEST")
// 2 unconsumed states with same external ID
val recordedBetweenExpression = TimeCondition(TimeInstantType.RECORDED, builder { between(start, end) })
@ -1853,13 +1852,12 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
// specifying Query on Linear state attributes
@Test
fun `unconsumed linear heads for linearId between two timestamps for a given external id`() {
val start = Instant.now()
val end = start.plus(6, ChronoUnit.SECONDS) //Enterprise: extended timeout for TC
database.transaction {
val start = services.clock.instant()
vaultFiller.fillWithSomeTestLinearStates(1, "TEST1")
vaultFiller.fillWithSomeTestLinearStates(1, "TEST2")
sleep(1000)
services.clock.advanceBy(1.seconds)
val end = services.clock.instant()
vaultFiller.fillWithSomeTestLinearStates(1, "TEST3")
// 2 unconsumed states with same external ID

View File

@ -31,7 +31,6 @@ dependencies {
// Configure these by hand. It should be a minimal subset of dependencies,
// and without any obviously non-deterministic ones such as Hibernate.
runtimeLibraries project(path: ':core-deterministic', configuration: 'runtimeArtifacts')
runtimeLibraries "io.github.lukehutch:fast-classpath-scanner:$fast_classpath_scanner_version"
runtimeLibraries "org.apache.qpid:proton-j:$protonj_version"
runtimeLibraries "org.iq80.snappy:snappy:$snappy_version"
}

View File

@ -54,9 +54,8 @@ abstract class AbstractAMQPSerializationScheme(
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, ConcurrentHashMap())
// TODO: This method of initialisation for the Whitelist and plugin serializers will have to change
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
companion object {
const val SCAN_SPEC_PROP_NAME = "amqp.custom.serialization.scanSpec"
private val serializationWhitelists: List<SerializationWhitelist> by lazy {
@ -64,25 +63,30 @@ abstract class AbstractAMQPSerializationScheme(
}
private val customSerializers: List<SerializationCustomSerializer<*, *>> by lazy {
val scanSpec: String? = System.getProperty(SCAN_SPEC_PROP_NAME)
if (scanSpec == null) {
emptyList()
} else {
FastClasspathScanner(scanSpec).addClassLoader(this::class.java.classLoader).scan()
scanClasspathForSerializers(scanSpec)
}
}
@StubOutForDJVM
private fun scanClasspathForSerializers(scanSpec: String): List<SerializationCustomSerializer<*, *>> =
this::class.java.classLoader.let { cl ->
FastClasspathScanner(scanSpec).addClassLoader(cl).scan()
.getNamesOfClassesImplementing(SerializationCustomSerializer::class.java)
.mapNotNull { this::class.java.classLoader.loadClass(it).asSubclass(SerializationCustomSerializer::class.java) }
.map { cl.loadClass(it).asSubclass(SerializationCustomSerializer::class.java) }
.filterNot { Modifier.isAbstract(it.modifiers) }
.map { it.kotlin.objectOrNewInstance() }
}
}
@DeleteForDJVM
val List<Cordapp>.customSerializers get() = flatMap { it.serializationCustomSerializers }.toSet()
}
// Parameter "context" is unused directy but passed in by reflection. Removing it will cause failures.
// Parameter "context" is unused directly but passed in by reflection. Removing it will cause failures.
private fun registerCustomSerializers(context: SerializationContext, factory: SerializerFactory) {
with(factory) {
register(publicKeySerializer)

View File

@ -241,7 +241,7 @@ open class MockServices private constructor(
override val vaultService: VaultService get() = throw UnsupportedOperationException()
override val contractUpgradeService: ContractUpgradeService get() = throw UnsupportedOperationException()
override val networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException()
override val clock: Clock get() = Clock.systemUTC()
override val clock: TestClock get() = TestClock(Clock.systemUTC())
override val myInfo: NodeInfo
get() {
return NodeInfo(listOf(NetworkHostAndPort("mock.node.services", 10000)), listOf(initialIdentity.identity), 1, serial = 1L)
@ -253,7 +253,7 @@ open class MockServices private constructor(
protected val servicesForResolution: ServicesForResolution get() = ServicesForResolutionImpl(identityService, attachments, cordappProvider, networkParameters, validatedTransactions)
internal fun makeVaultService(hibernateConfig: HibernateConfiguration, schemaService: SchemaService, database: CordaPersistence): VaultServiceInternal {
val vaultService = NodeVaultService(Clock.systemUTC(), keyManagementService, servicesForResolution, hibernateConfig, database)
val vaultService = NodeVaultService(clock, keyManagementService, servicesForResolution, hibernateConfig, database)
HibernateObserver.install(vaultService.rawUpdates, hibernateConfig, schemaService)
return vaultService
}

12
tools/shell-cli/README.md Normal file
View File

@ -0,0 +1,12 @@
Standalone Shell
----------------
Documentation for shell CLI can be found [here](http://docs.corda.net/website/releases/docs_head/shell.html)
To build this from the command line on Unix or MacOS:
Run ``./gradlew tools:shell-cli:buildShellCli`` to create a fat JAR in ``tools/shell-cli/build/libs``
To build this from the command line on Windows:
Run ``gradlew tools:shell-cli:buildShellCli`` to create a fat JAR in ``tools/shell-cli/build/libs``

View File

@ -1,103 +1,54 @@
buildscript {
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
}
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'maven-publish'
description 'Corda Shell CLI'
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
sourceSets {
integrationTest {
kotlin {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration-test/kotlin')
}
resources {
srcDir file('src/integration-test/resources')
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
test {
resources {
srcDir file('src/test/resources')
}
dependencies {
classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
}
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
compile project(':tools:shell')
// Unit testing helpers.
testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile project(':test-utils')
testCompile project(':finance')
}
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'com.jfrog.artifactory'
mainClassName = 'net.corda.tools.shell.StandaloneShellKt'
jar {
baseName 'corda-shell-cli'
dependencies {
compile project(':tools:shell')
compile group: 'org.slf4j', name: 'slf4j-simple', version: slf4j_version
testCompile(project(':test-utils')) {
exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
}
}
processResources {
from file("$rootDir/config/dev/log4j2.xml")
}
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
publishing {
publications {
shadow(MavenPublication) { publication ->
project.shadow.component(publication)
artifactId = "corda-tools-shell-cli"
}
}
}
shadowJar {
//transform(de.sebastianboegl.gradle.plugins.shadow.transformers.Log4j2PluginsFileTransformer)
archiveName = "corda-shell-cli-${version}.jar"
baseName = 'corda-shell-cli'
classifier = null
mainClassName = 'net.corda.tools.shell.StandaloneShellKt'
mergeServiceFiles()
}
task buildShellCli(dependsOn: shadowJar)
artifacts {
publish shadowJar {
classifier ""
}
}
jar {
classifier "ignore"
enabled = false
}
publish {
disableDefaultJar = true
name 'corda-tools-shell-cli'
}

View File

@ -60,7 +60,7 @@ dependencies {
// Manifests: for reading stuff from the manifest file.
compile "com.jcabi:jcabi-manifests:1.1"
// For logging.
// For logging, required for ANSIProgressRenderer.
compile "org.apache.logging.log4j:log4j-core:${log4j_version}"
// Unit testing helpers.