IRS demo fixes (#782)

* Increase max network map request size so the notary can register
* Suppress oracle service installation errors in non-oracle nodes
* Make demos automatically build capsule jars
This commit is contained in:
Andrzej Cichocki 2017-06-02 16:23:05 +01:00 committed by GitHub
parent c510e67ed5
commit 51ea9fec1a
17 changed files with 64 additions and 43 deletions

View File

@ -11,10 +11,13 @@ import kotlin.annotation.AnnotationTarget.CLASS
*
* The service class has to implement [net.corda.core.serialization.SerializeAsToken] to ensure correct usage within flows.
* (If possible extend [net.corda.core.serialization.SingletonSerializeAsToken] instead as it removes the boilerplate.)
*
* The annotated class should expose its [ServiceType] via a public static field named `type`, so that the service is
* only loaded in nodes that declare the type in their advertisedServices.
*/
// TODO Handle the singleton serialisation of Corda services automatically, removing the need to implement SerializeAsToken
// TODO Currently all nodes which load the plugin will attempt to load the service even if it's not revelant to them. The
// underlying problem is that the entire CorDapp jar is used as a dependency, when in fact it's just the client-facing
// bit of the CorDapp that should be depended on (e.g. the initiating flows).
@Target(CLASS)
annotation class CordaService
annotation class CordaService

View File

@ -43,8 +43,8 @@ dependencies {
exclude group: "bouncycastle"
}
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
}
mainClassName = "net.corda.docs.ClientRpcTutorialKt"

View File

@ -268,16 +268,31 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun installCordaServices(scanResult: ScanResult): List<SerializeAsToken> {
return scanResult.getClassesWithAnnotation(SerializeAsToken::class, CordaService::class).mapNotNull {
try {
installCordaService(it)
} catch (e: NoSuchMethodException) {
log.error("${it.name}, as a Corda service, must have a constructor with a single parameter " +
"of type ${PluginServiceHub::class.java.name}")
null
} catch (e: Exception) {
log.error("Unable to install Corda service ${it.name}", e)
null
}
tryInstallCordaService(it)
}
}
private fun <T : SerializeAsToken> tryInstallCordaService(serviceClass: Class<T>): T? {
/** TODO: This mechanism may get replaced by a different one, see comments on [CordaService]. */
val typeField = try {
serviceClass.getField("type")
} catch (e: NoSuchFieldException) {
null
}
if (typeField == null) {
log.warn("${serviceClass.name} does not have a type field, optimistically proceeding with install.")
} else if (info.serviceIdentities(typeField.get(null) as ServiceType).isEmpty()) {
return null
}
return try {
installCordaService(serviceClass)
} catch (e: NoSuchMethodException) {
log.error("${serviceClass.name}, as a Corda service, must have a constructor with a single parameter " +
"of type ${PluginServiceHub::class.java.name}")
null
} catch (e: Exception) {
log.error("Unable to install Corda service ${serviceClass.name}", e)
null
}
}

View File

@ -18,6 +18,7 @@ import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor
import net.corda.node.services.api.AbstractNodeService
import net.corda.node.services.api.ServiceHubInternal
@ -135,10 +136,10 @@ 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
* Maximum credible size for a registration request. Generally requests are around 2000-6000 bytes, so this gives a
* 10 times overhead.
*/
private const val MAX_SIZE_REGISTRATION_REQUEST_BYTES = 5500
private const val MAX_SIZE_REGISTRATION_REQUEST_BYTES = 40000
private val logger = loggerFor<AbstractNetworkMapService>()
}
@ -232,7 +233,9 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
}
private fun processRegistrationRequest(request: RegistrationRequest): RegistrationResponse {
if (request.wireReg.raw.size > MAX_SIZE_REGISTRATION_REQUEST_BYTES) {
val requestSize = request.wireReg.raw.size
logger.debug { "Received registration request of size: $requestSize" }
if (requestSize > MAX_SIZE_REGISTRATION_REQUEST_BYTES) {
return RegistrationResponse("Request is too big")
}

View File

@ -26,8 +26,8 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':test-utils')

View File

@ -26,8 +26,8 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':client:jfx')
compile project(':client:rpc')

View File

@ -30,8 +30,8 @@ dependencies {
testCompile "org.assertj:assertj-core:${assertj_version}"
// Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':finance')
compile project(':webserver')

View File

@ -39,7 +39,7 @@ class IRSDemoTest : IntegrationTestCategory {
systemProperties = mapOf("net.corda.node.cordapp.scan.package" to "net.corda.irs"))
{
val (controller, nodeA, nodeB) = Futures.allAsList(
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.type))),
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.Oracle.type))),
startNode(DUMMY_BANK_A.name, rpcUsers = listOf(rpcUser)),
startNode(DUMMY_BANK_B.name)
).getOrThrow()

View File

@ -17,7 +17,7 @@ import net.corda.node.services.transactions.SimpleNotaryService
fun main(args: Array<String>) {
driver(dsl = {
val (controller, nodeA, nodeB) = Futures.allAsList(
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.type))),
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type), ServiceInfo(NodeInterestRates.Oracle.type))),
startNode(DUMMY_BANK_A.name),
startNode(DUMMY_BANK_B.name)
).getOrThrow()

View File

@ -49,8 +49,6 @@ import kotlin.collections.set
* for signing.
*/
object NodeInterestRates {
val type = ServiceType.corda.getSubType("interest_rates")
// DOCSTART 2
@InitiatedBy(RatesFixFlow.FixSignFlow::class)
class FixSignHandler(val otherParty: Party) : FlowLogic<Unit>() {
@ -95,6 +93,11 @@ object NodeInterestRates {
)
// DOCEND 3
companion object {
@JvmField
val type = ServiceType.corda.getSubType("interest_rates")
}
private object Table : JDBCHashedTable("demo_interest_rate_fixes") {
val name = varchar("index_name", length = 255)
val forDay = localDate("for_day")

View File

@ -10,6 +10,7 @@ import net.corda.core.identity.Party
import net.corda.core.node.services.ServiceType
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.TransactionBuilder
import net.corda.irs.api.NodeInterestRates
import net.corda.irs.flows.FixingFlow
import net.corda.irs.utilities.suggestInterestRateAnnouncementTimeWindow
import org.apache.commons.jexl3.JexlBuilder
@ -190,10 +191,6 @@ class FloatingRatePaymentEvent(date: LocalDate,
class InterestRateSwap : Contract {
override val legalContractReference = SecureHash.sha256("is_this_the_text_of_the_contract ? TBD")
companion object {
val oracleType = ServiceType.corda.getSubType("interest_rates")
}
/**
* This Common area contains all the information that is not leg specific.
*/
@ -665,7 +662,7 @@ class InterestRateSwap : Contract {
override val contract = IRS_PROGRAM_ID
override val oracleType: ServiceType
get() = InterestRateSwap.oracleType
get() = NodeInterestRates.Oracle.type
override val ref = common.tradeID

View File

@ -121,7 +121,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger): MockNetwork.MockNode {
require(advertisedServices.containsType(NodeInterestRates.type))
require(advertisedServices.containsType(NodeInterestRates.Oracle.type))
val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory,
myLegalName = RATES_SERVICE_NAME,
@ -166,7 +166,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
= network.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode
val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
val ratesOracle: SimulatedNode
= network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.type)) as SimulatedNode
= network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type)) as SimulatedNode
// All nodes must be in one of these two lists for the purposes of the visualiser tool.
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)

View File

@ -209,7 +209,7 @@ class NodeInterestRatesTest {
fun `network tearoff`() {
val net = MockNetwork()
val n1 = net.createNotaryNode()
val n2 = net.createNode(n1.info.address, advertisedServices = ServiceInfo(NodeInterestRates.type))
val n2 = net.createNode(n1.info.address, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type))
n2.registerInitiatedFlow(NodeInterestRates.FixQueryHandler::class.java)
n2.registerInitiatedFlow(NodeInterestRates.FixSignHandler::class.java)
n2.database.transaction {
@ -217,7 +217,7 @@ class NodeInterestRatesTest {
}
val tx = TransactionType.General.Builder(null)
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val oracle = n2.info.serviceIdentities(NodeInterestRates.type).first()
val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first()
val flow = FilteredRatesFlow(tx, oracle, fixOf, "0.675".bd, "0.1".bd)
LogHelper.setLevel("rates")
net.runNetwork()

View File

@ -12,8 +12,8 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':finance')
testCompile project(':test-utils')

View File

@ -18,8 +18,8 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':client:jfx')
compile project(':client:rpc')

View File

@ -31,8 +31,8 @@ dependencies {
testCompile "org.assertj:assertj-core:${assertj_version}"
// Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':node')
compile project(':webserver')

View File

@ -27,8 +27,8 @@ dependencies {
testCompile "org.assertj:assertj-core:${assertj_version}"
// Corda integration dependencies
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
runtime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
compile project(':core')
compile project(':finance')
compile project(':test-utils')