Merge branch 'master' into dynamic-loading

This commit is contained in:
sofusmortensen 2016-04-03 13:58:28 +02:00
commit 88a7406ec9
34 changed files with 1250 additions and 213 deletions

View File

@ -1,7 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests" type="JUnit" factoryName="JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="r3prototyping_test" />
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" value="" />
@ -14,7 +14,7 @@
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
<value defaultName="wholeProject" />
</option>
<envs />
<patterns />

View File

@ -8,6 +8,15 @@
package contracts
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.fasterxml.jackson.databind.type.SimpleType
import core.*
import core.crypto.SecureHash
import core.node.services.DummyTimestampingAuthority
@ -15,6 +24,7 @@ import org.apache.commons.jexl3.JexlBuilder
import org.apache.commons.jexl3.MapContext
import java.math.BigDecimal
import java.math.RoundingMode
import java.security.PublicKey
import java.time.LocalDate
import java.util.*
@ -167,8 +177,6 @@ class InterestRateSwap() : Contract {
val hashLegalDocs: String
)
data class Expression(val expr: String)
/**
* The Calculation data class is "mutable" through out the life of the swap, as in, it's the only thing that contains
* data that will changed from state to state (Recall that the design insists that everything is immutable, so we actually
@ -177,7 +185,7 @@ class InterestRateSwap() : Contract {
data class Calculation(
val expression: Expression,
val floatingLegPaymentSchedule: Map<LocalDate, FloatingRatePaymentEvent>,
val fixedLegpaymentSchedule: Map<LocalDate, FixedRatePaymentEvent>
val fixedLegPaymentSchedule: Map<LocalDate, FixedRatePaymentEvent>
) {
/**
* Gets the date of the next fixing.
@ -185,7 +193,7 @@ class InterestRateSwap() : Contract {
*/
fun nextFixingDate(): LocalDate? {
return floatingLegPaymentSchedule.
filter { it.value.rate is OracleRetrievableReferenceRate }.// TODO - a better way to determine what fixings remain to be fixed
filter { it.value.rate is ReferenceRate }.// TODO - a better way to determine what fixings remain to be fixed
minBy { it.value.fixingDate.toEpochDay() }?.value?.fixingDate
}
@ -203,7 +211,7 @@ class InterestRateSwap() : Contract {
val newFloatingLPS = floatingLegPaymentSchedule + (paymentEvent.date to paymentEvent.withNewRate(newRate))
return Calculation(expression = expression,
floatingLegPaymentSchedule = newFloatingLPS,
fixedLegpaymentSchedule = fixedLegpaymentSchedule)
fixedLegPaymentSchedule = fixedLegPaymentSchedule)
}
fun exportSchedule() {
@ -297,7 +305,7 @@ class InterestRateSwap() : Contract {
*/
override fun verify(tx: TransactionForVerification) {
val command = tx.commands.requireSingleCommand<InterestRateSwap.Commands>()
val time = tx.getTimestampBy(DummyTimestampingAuthority.identity)?.midpoint
val time = tx.commands.getTimestampByName("Mock Company 0", "Bank of Zurich")?.midpoint
if (time == null) throw IllegalArgumentException("must be timestamped")
val irs = tx.outStates.filterIsInstance<InterestRateSwap.State>().single()
@ -306,7 +314,7 @@ class InterestRateSwap() : Contract {
requireThat {
"There are no in states for an agreement" by tx.inStates.isEmpty()
"The fixed rate is non zero" by (irs.fixedLeg.fixedRate != FixedRate(PercentageRatioUnit("0.0")))
"There are events in the fix schedule" by (irs.calculation.fixedLegpaymentSchedule.size > 0)
"There are events in the fix schedule" by (irs.calculation.fixedLegPaymentSchedule.size > 0)
"There are events in the float schedule" by (irs.calculation.floatingLegPaymentSchedule.size > 0)
// "There are fixes in the schedule" by (irs.calculation.floatingLegPaymentSchedule!!.size > 0)
// TODO: shortlist of other tests
@ -348,8 +356,14 @@ class InterestRateSwap() : Contract {
val floatingLeg: FloatingLeg,
val calculation: Calculation,
val common: Common
) : ContractState {
) : LinearState {
override val contract = IRS_PROGRAM_ID
override val thread = SecureHash.sha256(common.tradeID)
override val ref = common.tradeID
override fun isRelevant(ourKeys: Set<PublicKey>): Boolean {
return (fixedLeg.fixedRatePayer.owningKey in ourKeys) || (floatingLeg.floatingRatePayer.owningKey in ourKeys)
}
/**
* For evaluating arbitrary java on the platform
@ -408,9 +422,6 @@ class InterestRateSwap() : Contract {
var floatingLegPaymentSchedule: MutableMap<LocalDate, FloatingRatePaymentEvent> = HashMap()
periodStartDate = floatingLeg.effectiveDate
// TODO: Temporary until implemented via Rates Oracle.
val telerate = TelerateOracle("3750")
// Now create a schedule for the floating and fixes.
for (periodEndDate in dates) {
val paymentEvent = FloatingRatePaymentEvent(
@ -421,8 +432,7 @@ class InterestRateSwap() : Contract {
floatingLeg.dayCountBasisYear,
calcFixingDate(periodStartDate, floatingLeg.fixingPeriod, floatingLeg.fixingCalendar),
floatingLeg.notional,
// TODO: OracleRetrievableReferenceRate will be replaced via oracle v soon.
OracleRetrievableReferenceRate(telerate, floatingLeg.indexTenor, floatingLeg.index)
ReferenceRate(floatingLeg.indexSource, floatingLeg.indexTenor, floatingLeg.index)
)
floatingLegPaymentSchedule.put(periodEndDate, paymentEvent)

View File

@ -10,6 +10,6 @@ package contracts
fun InterestRateSwap.State.exportIRSToCSV() : String =
"Fixed Leg\n" + FixedRatePaymentEvent.CSVHeader + "\n" +
this.calculation.fixedLegpaymentSchedule.toSortedMap().values.map{ it.asCSV() }.joinToString("\n") + "\n" +
this.calculation.fixedLegPaymentSchedule.toSortedMap().values.map{ it.asCSV() }.joinToString("\n") + "\n" +
"Floating Leg\n" + FloatingRatePaymentEvent.CSVHeader + "\n" +
this.calculation.floatingLegPaymentSchedule.toSortedMap().values.map{ it.asCSV() }.joinToString("\n") + "\n"

View File

@ -1,5 +1,13 @@
package contracts
import com.fasterxml.jackson.core.JsonParseException
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer
import com.fasterxml.jackson.databind.type.SimpleType
import core.Amount
import core.Tenor
import java.math.BigDecimal
@ -50,43 +58,7 @@ open class FloatingRate: Rate(null)
* So a reference rate is a rate that takes its value from a source at a given date
* e.g. LIBOR 6M as of 17 March 2016. Hence it requires a source (name) and a value date in the getAsOf(..) method.
*/
abstract class ReferenceRate(val name: String): FloatingRate() {
abstract fun getAsOf(date: LocalDate?) : RatioUnit
}
/**
* A concrete implementation of the above for testing purposes
*/
open class TestReferenceRate(val testrate: String) : ReferenceRate(testrate) {
override fun getAsOf(date: LocalDate?) : RatioUnit {
return testrate.percent
}
}
/**
* This represents a source of data.
*/
abstract class Oracle() { abstract fun retrieve(tenor: Tenor, date: LocalDate) : RatioUnit }
class ReutersOracle() : Oracle() {
override fun retrieve(tenor: Tenor, date: LocalDate): RatioUnit {
TODO("Reuters Oracle retrieval")
}
}
class TelerateOracle(page: String) : Oracle() {
override fun retrieve(tenor: Tenor, date: LocalDate): RatioUnit {
TODO("Telerate Oracle retrieval")
}
}
/**
* A Reference rate that is retrieved via an Oracle.
*/
open class OracleRetrievableReferenceRate(val oracle: Oracle, val tenor: Tenor, referenceRate: String) : ReferenceRate(referenceRate) {
override fun getAsOf(date: LocalDate?): RatioUnit {
return oracle.retrieve(tenor,date!!)
}
class ReferenceRate(val oracle: String, val tenor: Tenor, val name: String) : FloatingRate() {
override fun toString(): String = "$name - $tenor"
}

View File

@ -47,4 +47,7 @@ dependencies {
// Apache JEXL: An embeddable expression evaluation library.
// This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API.
compile "org.apache.commons:commons-jexl3:3.0"
// For JSON
compile "com.fasterxml.jackson.core:jackson-databind:2.5.5"
}

View File

@ -8,6 +8,14 @@
package core
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import java.math.BigDecimal
import java.time.DayOfWeek
import java.time.LocalDate
@ -82,7 +90,25 @@ data class FixOf(val name: String, val forDay: LocalDate, val ofTenor: Tenor)
/** A [Fix] represents a named interest rate, on a given day, for a given duration. It can be embedded in a tx. */
data class Fix(val of: FixOf, val value: BigDecimal) : CommandData
/**
* Represents a textual expression of e.g. a formula
*
*/
@JsonDeserialize(using = ExpressionDeserializer::class)
@JsonSerialize(using = ExpressionSerializer::class)
data class Expression(val expr: String)
object ExpressionSerializer: JsonSerializer<Expression>() {
override fun serialize(expr: Expression, generator: JsonGenerator, provider: SerializerProvider) {
generator.writeString(expr.expr)
}
}
object ExpressionDeserializer: JsonDeserializer<Expression>() {
override fun deserialize(parser: JsonParser, context: DeserializationContext): Expression {
return Expression(parser.text)
}
}
/**
* Placeholder class for the Tenor datatype - which is a standardised duration of time until maturity */

View File

@ -3,4 +3,49 @@
LIBOR 2016-03-16 1M = 0.678
LIBOR 2016-03-16 2M = 0.655
EURIBOR 2016-03-15 1M = 0.123
EURIBOR 2016-03-15 2M = 0.111
EURIBOR 2016-03-15 2M = 0.111
LIBOR 2016-03-08 3M = 0.01
LIBOR 2016-06-08 3M = 0.01
LIBOR 2016-09-08 3M = 0.01
LIBOR 2016-12-08 3M = 0.01
LIBOR 2017-03-08 3M = 0.01
LIBOR 2017-06-08 3M = 0.01
LIBOR 2017-09-07 3M = 0.01
LIBOR 2017-12-07 3M = 0.01
LIBOR 2018-03-08 3M = 0.01
LIBOR 2018-06-07 3M = 0.01
LIBOR 2018-09-06 3M = 0.01
LIBOR 2018-12-06 3M = 0.01
LIBOR 2019-03-07 3M = 0.01
LIBOR 2019-06-06 3M = 0.01
LIBOR 2019-09-06 3M = 0.01
LIBOR 2019-12-06 3M = 0.01
LIBOR 2020-03-06 3M = 0.01
LIBOR 2020-06-08 3M = 0.01
LIBOR 2020-09-08 3M = 0.01
LIBOR 2020-12-08 3M = 0.01
LIBOR 2021-03-08 3M = 0.01
LIBOR 2021-06-08 3M = 0.01
LIBOR 2021-09-08 3M = 0.01
LIBOR 2021-12-08 3M = 0.01
LIBOR 2022-03-08 3M = 0.01
LIBOR 2022-06-08 3M = 0.01
LIBOR 2022-09-08 3M = 0.01
LIBOR 2022-12-08 3M = 0.01
LIBOR 2023-03-08 3M = 0.01
LIBOR 2023-06-08 3M = 0.01
LIBOR 2023-09-07 3M = 0.01
LIBOR 2023-12-07 3M = 0.01
LIBOR 2024-03-07 3M = 0.01
LIBOR 2024-06-06 3M = 0.01
LIBOR 2024-09-06 3M = 0.01
LIBOR 2024-12-06 3M = 0.01
LIBOR 2025-03-06 3M = 0.01
LIBOR 2025-06-06 3M = 0.01
LIBOR 2025-09-08 3M = 0.01
LIBOR 2025-12-08 3M = 0.01
LIBOR 2026-03-06 3M = 0.01
LIBOR 2026-06-08 3M = 0.01
LIBOR 2026-09-08 3M = 0.01
LIBOR 2026-12-08 3M = 0.01

View File

@ -7,6 +7,7 @@ import core.crypto.SecureHash
import core.node.AbstractNode
import core.protocols.ProtocolLogic
import core.serialization.SerializedBytes
import core.utilities.ANSIProgressRenderer
import java.time.LocalDateTime
import java.util.*
import kotlin.reflect.KParameter
@ -87,6 +88,7 @@ class APIServerImpl(val node: AbstractNode): APIServer {
}
// If we get here then we matched every parameter
val protocol = constructor.callBy(params) as ProtocolLogic<*>
ANSIProgressRenderer.progressTracker = protocol.progressTracker
val future = node.smm.add("api-call",protocol)
return future
}

View File

@ -0,0 +1,33 @@
package api
import javax.ws.rs.container.ContainerRequestContext
import javax.ws.rs.container.ContainerResponseContext
import javax.ws.rs.container.ContainerResponseFilter
import javax.ws.rs.ext.Provider
/**
* This adds headers needed for cross site scripting on API clients
*/
@Provider
class ResponseFilter: ContainerResponseFilter {
override fun filter(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) {
val headers = responseContext.headers
/**
* TODO we need to revisit this for security reasons
*
* We don't want this scriptable from any web page anywhere, but for demo reasons
* we're making this really easy to access pending a proper security approach including
* access control and authentication at a network and software level
*
*/
headers.add("Access-Control-Allow-Origin","*")
if(requestContext.method == "OPTIONS") {
headers.add("Access-Control-Allow-Headers", "Content-Type,Accept,Origin")
headers.add("Access-Control-Allow-Methods", "POST,PUT,GET,OPTIONS")
}
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.messaging
import core.Party
import core.crypto.DummyPublicKey
import java.util.*
/** Info about a network node that has is operated by some sort of verified identity. */
data class LegallyIdentifiableNode(val address: SingleMessageRecipient, val identity: Party)
/**
* A network map contains lists of nodes on the network along with information about their identity keys, services
* they provide and host names or IP addresses where they can be connected to. A reasonable architecture for the
* network map service might be one like the Tor directory authorities, where several nodes linked by RAFT or Paxos
* elect a leader and that leader distributes signed documents describing the network layout. Those documents can
* then be cached by every node and thus a network map can be retrieved given only a single successful peer connection.
*
* This interface assumes fast, synchronous access to an in-memory map.
*/
interface NetworkMapService {
val timestampingNodes: List<LegallyIdentifiableNode>
val partyNodes: List<LegallyIdentifiableNode>
fun nodeForPartyName(name: String): LegallyIdentifiableNode? = partyNodes.singleOrNull { it.identity.name == name }
}
// TODO: Move this to the test tree once a real network map is implemented and this scaffolding is no longer needed.
class MockNetworkMapService : NetworkMapService {
data class MockAddress(val id: String): SingleMessageRecipient
override val timestampingNodes = Collections.synchronizedList(ArrayList<LegallyIdentifiableNode>())
override val partyNodes = Collections.synchronizedList(ArrayList<LegallyIdentifiableNode>())
init {
partyNodes.add(LegallyIdentifiableNode(MockAddress("excalibur:8080"), Party("Excalibur", DummyPublicKey("Excalibur"))))
partyNodes.add(LegallyIdentifiableNode(MockAddress("another:8080"), Party("ANOther", DummyPublicKey("ANOther"))))
}
}

View File

@ -168,10 +168,11 @@ class StateMachineManager(val serviceHub: ServiceHub, val runInThread: Executor)
fun <T> add(loggerName: String, logic: ProtocolLogic<T>): ListenableFuture<T> {
val logger = LoggerFactory.getLogger(loggerName)
val fiber = ProtocolStateMachine(logic)
// Need to add before iterating in case of immediate completion
_stateMachines.add(logic)
iterateStateMachine(fiber, serviceHub.networkService, logger, null, null) {
it.start()
}
_stateMachines.add(logic)
totalStartedProtocols.inc()
return fiber.resultFuture
}

View File

@ -20,10 +20,12 @@ import api.APIServer
import api.APIServerImpl
import com.codahale.metrics.MetricRegistry
import contracts.*
import core.*
import core.Contract
import core.Party
import core.crypto.SecureHash
import core.crypto.generateKeyPair
import core.messaging.*
import core.messaging.MessagingService
import core.messaging.StateMachineManager
import core.node.services.*
import core.serialization.deserialize
import core.serialization.serialize
@ -68,7 +70,11 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
override val clock: Clock get() = platformClock
}
val legallyIdentifableAddress: LegallyIdentifiableNode get() = LegallyIdentifiableNode(net.myAddress, storage.myLegalIdentity)
val legallyIdentifiableAddress: LegallyIdentifiableNode by lazy {
LegallyIdentifiableNode(net.myAddress, storage.myLegalIdentity, findMyLocation())
}
protected open fun findMyLocation(): PhysicalLocation? = CityDatabase[configuration.nearestCity]
lateinit var storage: StorageService
lateinit var smm: StateMachineManager

View File

@ -9,9 +9,10 @@
package core.node
import api.Config
import api.ResponseFilter
import com.codahale.metrics.JmxReporter
import com.google.common.net.HostAndPort
import core.messaging.LegallyIdentifiableNode
import core.node.services.LegallyIdentifiableNode
import core.messaging.MessagingService
import core.node.services.ArtemisMessagingService
import core.node.servlets.AttachmentDownloadServlet
@ -94,6 +95,7 @@ class Node(dir: Path, val p2pAddr: HostAndPort, configuration: NodeConfiguration
val resourceConfig = ResourceConfig()
// Add your API provider classes (annotated for JAX-RS) here
resourceConfig.register(Config(services))
resourceConfig.register(ResponseFilter())
resourceConfig.register(api)
// Give the app a slightly better name in JMX rather than a randomly generated one and enable JMX
resourceConfig.addProperties(mapOf(ServerProperties.APPLICATION_NAME to "node.api",

View File

@ -15,6 +15,7 @@ import kotlin.reflect.KProperty
interface NodeConfiguration {
val myLegalName: String
val exportJMXto: String
val nearestCity: String
}
// Allow the use of "String by config" syntax. TODO: Make it more flexible.
@ -23,4 +24,5 @@ operator fun Config.getValue(receiver: NodeConfigurationFromConfig, metadata: KP
class NodeConfigurationFromConfig(val config: Config = ConfigFactory.load()) : NodeConfiguration {
override val myLegalName: String by config
override val exportJMXto: String by config
override val nearestCity: String by config
}

View File

@ -135,43 +135,45 @@ class ArtemisMessagingService(val directory: Path, val myHostPort: HostAndPort)
session.createQueue(myHostPort.toString(), "inbound", false)
inboundConsumer = session.createConsumer("inbound").setMessageHandler { message: ClientMessage ->
// This code runs for every inbound message.
if (!message.containsProperty(TOPIC_PROPERTY)) {
log.warn("Received message without a ${TOPIC_PROPERTY} property, ignoring")
// TODO: Figure out whether we always need to acknowledge messages, even when invalid.
return@setMessageHandler
}
val topic = message.getStringProperty(TOPIC_PROPERTY)
// Because handlers is a COW list, the loop inside filter will operate on a snapshot. Handlers being added
// or removed whilst the filter is executing will not affect anything.
val deliverTo = handlers.filter { if (it.topic.isBlank()) true else it.topic == topic }
try {
if (!message.containsProperty(TOPIC_PROPERTY)) {
log.warn("Received message without a ${TOPIC_PROPERTY} property, ignoring")
return@setMessageHandler
}
val topic = message.getStringProperty(TOPIC_PROPERTY)
// Because handlers is a COW list, the loop inside filter will operate on a snapshot. Handlers being added
// or removed whilst the filter is executing will not affect anything.
val deliverTo = handlers.filter { if (it.topic.isBlank()) true else it.topic == topic }
if (deliverTo.isEmpty()) {
// This should probably be downgraded to a trace in future, so the protocol can evolve with new topics
// without causing log spam.
log.warn("Received message for $topic that doesn't have any registered handlers.")
return@setMessageHandler
}
if (deliverTo.isEmpty()) {
// This should probably be downgraded to a trace in future, so the protocol can evolve with new topics
// without causing log spam.
log.warn("Received message for $topic that doesn't have any registered handlers.")
return@setMessageHandler
}
val bits = ByteArray(message.bodySize)
message.bodyBuffer.readBytes(bits)
val bits = ByteArray(message.bodySize)
message.bodyBuffer.readBytes(bits)
val msg = object : Message {
override val topic = topic
override val data: ByteArray = bits
override val debugTimestamp: Instant = Instant.ofEpochMilli(message.timestamp)
override val debugMessageID: String = message.messageID.toString()
override fun serialise(): ByteArray = bits
}
for (handler in deliverTo) {
(handler.executor ?: RunOnCallerThread).execute {
try {
handler.callback(msg, handler)
} catch(e: Exception) {
log.error("Caught exception whilst executing message handler for $topic", e)
val msg = object : Message {
override val topic = topic
override val data: ByteArray = bits
override val debugTimestamp: Instant = Instant.ofEpochMilli(message.timestamp)
override val debugMessageID: String = message.messageID.toString()
override fun serialise(): ByteArray = bits
}
for (handler in deliverTo) {
(handler.executor ?: RunOnCallerThread).execute {
try {
handler.callback(msg, handler)
} catch(e: Exception) {
log.error("Caught exception whilst executing message handler for $topic", e)
}
}
}
} finally {
message.acknowledge()
}
message.acknowledge()
}
session.start()

View File

@ -0,0 +1,106 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services
import core.Party
import core.crypto.DummyPublicKey
import core.messaging.SingleMessageRecipient
import java.util.*
/** Info about a network node that has operated by some sort of verified identity. */
data class LegallyIdentifiableNode(val address: SingleMessageRecipient, val identity: Party,
val physicalLocation: PhysicalLocation? = null)
/**
* A network map contains lists of nodes on the network along with information about their identity keys, services
* they provide and host names or IP addresses where they can be connected to. A reasonable architecture for the
* network map service might be one like the Tor directory authorities, where several nodes linked by RAFT or Paxos
* elect a leader and that leader distributes signed documents describing the network layout. Those documents can
* then be cached by every node and thus a network map can be retrieved given only a single successful peer connection.
*
* This interface assumes fast, synchronous access to an in-memory map.
*/
interface NetworkMapService {
val timestampingNodes: List<LegallyIdentifiableNode>
val ratesOracleNodes: List<LegallyIdentifiableNode>
val partyNodes: List<LegallyIdentifiableNode>
fun nodeForPartyName(name: String): LegallyIdentifiableNode? = partyNodes.singleOrNull { it.identity.name == name }
}
// TODO: Move this to the test tree once a real network map is implemented and this scaffolding is no longer needed.
class MockNetworkMapService : NetworkMapService {
data class MockAddress(val id: String): SingleMessageRecipient
override val timestampingNodes = Collections.synchronizedList(ArrayList<LegallyIdentifiableNode>())
override val ratesOracleNodes = Collections.synchronizedList(ArrayList<LegallyIdentifiableNode>())
override val partyNodes = Collections.synchronizedList(ArrayList<LegallyIdentifiableNode>())
init {
partyNodes.add(LegallyIdentifiableNode(MockAddress("excalibur:8080"), Party("Excalibur", DummyPublicKey("Excalibur"))))
partyNodes.add(LegallyIdentifiableNode(MockAddress("another:8080"), Party("ANOther", DummyPublicKey("ANOther"))))
}
}
/** A latitude/longitude pair. */
data class WorldCoordinate(val latitude: Double, val longitude: Double) {
init {
require(latitude in -90..90)
require(longitude in -180..180)
}
/**
* Convert to screen coordinates using the Mercator projection. You should have a world map image that
* you know the precise extents of for this function to work.
*
* Note that no world map ever has latitude extents of -90 to 90 because at these extremes the mapping tends
* to infinity. Google Maps, for example, uses a square map image, and square maps yield latitude extents
* of 85.0511 to -85.0511 = arctan(sinh(π)).
*/
fun project(screenWidth: Double, screenHeight: Double, topLatitude: Double, bottomLatitude: Double,
leftLongitude: Double, rightLongitude: Double): Pair<Double, Double> {
require(latitude in bottomLatitude..topLatitude)
require(longitude in leftLongitude..rightLongitude)
fun deg2rad(deg: Double) = deg * Math.PI / 180.0
val leftLngRad = deg2rad(leftLongitude)
val rightLngRad = deg2rad(rightLongitude)
fun longitudeToScreenX(lng: Double) = screenWidth * (deg2rad(lng) - leftLngRad) / (rightLngRad - leftLngRad)
fun screenYRelative(latDeg: Double) = Math.log(Math.tan(latDeg / 360.0 * Math.PI + Math.PI / 4))
val topLatRel = screenYRelative(topLatitude)
val bottomLatRel = screenYRelative(bottomLatitude)
fun latitudeToScreenY(lat: Double) = screenHeight * (screenYRelative(lat) - topLatRel) / (bottomLatRel - topLatRel)
return Pair(longitudeToScreenX(longitude), latitudeToScreenY(latitude))
}
}
/**
* A labelled [WorldCoordinate], where the label is human meaningful. For example, the name of the nearest city.
* Labels should not refer to non-landmarks, for example, they should not contain the names of organisations.
*/
data class PhysicalLocation(val coordinate: WorldCoordinate, val description: String)
/**
* A simple lookup table of city names to their coordinates. Lookups are case insensitive.
*/
object CityDatabase {
private val cityMap = HashMap<String, PhysicalLocation>()
init {
javaClass.getResourceAsStream("cities.txt").bufferedReader().useLines { lines ->
for (line in lines) {
if (line.startsWith("#")) continue
val (name, lng, lat) = line.split('\t')
cityMap[name.toLowerCase()] = PhysicalLocation(WorldCoordinate(lat.toDouble(), lng.toDouble()), name)
}
}
}
operator fun get(name: String) = cityMap[name.toLowerCase()]
}

View File

@ -13,7 +13,7 @@ import contracts.Cash
import core.*
import core.crypto.SecureHash
import core.messaging.MessagingService
import core.messaging.NetworkMapService
import core.node.services.NetworkMapService
import java.io.InputStream
import java.security.KeyPair
import java.security.PrivateKey

View File

@ -11,17 +11,22 @@ package core.testing
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.MoreExecutors
import core.node.services.DummyTimestampingAuthority
import core.ThreadBox
import core.crypto.sha256
import core.messaging.*
import core.node.services.DummyTimestampingAuthority
import core.node.services.LegallyIdentifiableNode
import core.node.services.NodeTimestamperService
import core.utilities.loggerFor
import rx.Observable
import rx.subjects.PublishSubject
import java.time.Duration
import java.time.Instant
import java.util.*
import java.util.concurrent.Executor
import java.util.concurrent.LinkedBlockingQueue
import javax.annotation.concurrent.ThreadSafe
import kotlin.concurrent.schedule
import kotlin.concurrent.thread
/**
@ -66,8 +71,33 @@ class InMemoryMessagingNetwork {
return Builder(manuallyPumped, Handle(id))
}
private val _allMessages = PublishSubject.create<Triple<SingleMessageRecipient, Message, MessageRecipients>>()
/** A stream of (sender, message, recipients) triples */
val allMessages: Observable<Triple<SingleMessageRecipient, Message, MessageRecipients>> = _allMessages
interface LatencyCalculator {
fun between(sender: SingleMessageRecipient, receiver: SingleMessageRecipient): Duration
}
/** This can be set to an object which can inject artificial latency between sender/recipient pairs. */
@Volatile var latencyCalculator: LatencyCalculator? = null
private val timer = Timer()
@Synchronized
private fun msgSend(message: Message, recipients: MessageRecipients) {
private fun msgSend(from: InMemoryMessaging, message: Message, recipients: MessageRecipients) {
val calc = latencyCalculator
if (calc != null && recipients is SingleMessageRecipient) {
// Inject some artificial latency.
timer.schedule(calc.between(from.myAddress, recipients).toMillis()) {
msgSendInternal(from, message, recipients)
}
} else {
msgSendInternal(from, message, recipients)
}
_allMessages.onNext(Triple(from.myAddress, message, recipients))
}
private fun msgSendInternal(from: InMemoryMessaging, message: Message, recipients: MessageRecipients) {
when (recipients) {
is Handle -> getQueueForHandle(recipients).add(message)
@ -173,7 +203,7 @@ class InMemoryMessagingNetwork {
Pair(handler, items)
}
for (it in items)
msgSend(it, handle)
msgSend(this, it, handle)
return handler
}
@ -184,7 +214,7 @@ class InMemoryMessagingNetwork {
override fun send(message: Message, target: MessageRecipients) {
check(running)
msgSend(message, target)
msgSend(this, message, target)
}
override fun stop() {

View File

@ -11,11 +11,13 @@ package core.testing
import com.google.common.jimfs.Jimfs
import com.google.common.util.concurrent.MoreExecutors
import core.Party
import core.messaging.LegallyIdentifiableNode
import core.messaging.MessagingService
import core.messaging.SingleMessageRecipient
import core.node.AbstractNode
import core.node.NodeConfiguration
import core.node.services.FixedIdentityService
import core.node.services.LegallyIdentifiableNode
import core.node.services.PhysicalLocation
import core.utilities.loggerFor
import org.slf4j.Logger
import java.nio.file.Files
@ -33,7 +35,8 @@ import java.util.concurrent.Executors
* for message exchanges to take place (and associated handlers to run), you must call the [runNetwork]
* method.
*/
class MockNetwork(private val threadPerNode: Boolean = false) {
class MockNetwork(private val threadPerNode: Boolean = false,
private val defaultFactory: Factory = MockNetwork.DefaultFactory) {
private var counter = 0
val filesystem = Jimfs.newFileSystem(com.google.common.jimfs.Configuration.unix())
val messagingNetwork = InMemoryMessagingNetwork()
@ -48,6 +51,19 @@ class MockNetwork(private val threadPerNode: Boolean = false) {
Files.createDirectory(filesystem.getPath("/nodes"))
}
/** Allows customisation of how nodes are created. */
interface Factory {
fun create(dir: Path, config: NodeConfiguration, network: MockNetwork,
timestamperAddr: LegallyIdentifiableNode?): MockNode
}
object DefaultFactory : Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork,
timestamperAddr: LegallyIdentifiableNode?): MockNode {
return MockNode(dir, config, network, timestamperAddr)
}
}
open class MockNode(dir: Path, config: NodeConfiguration, val mockNet: MockNetwork,
withTimestamper: LegallyIdentifiableNode?, val forcedID: Int = -1) : AbstractNode(dir, config, withTimestamper, Clock.systemUTC()) {
override val log: Logger = loggerFor<MockNode>()
@ -69,6 +85,9 @@ class MockNetwork(private val threadPerNode: Boolean = false) {
override fun makeIdentityService() = FixedIdentityService(mockNet.identities)
// There is no need to slow down the unit tests by initialising CityDatabase
override fun findMyLocation(): PhysicalLocation? = null
override fun start(): MockNode {
super.start()
mockNet.identities.add(storage.myLegalIdentity)
@ -77,8 +96,7 @@ class MockNetwork(private val threadPerNode: Boolean = false) {
}
/** Returns a started node, optionally created by the passed factory method */
fun createNode(withTimestamper: LegallyIdentifiableNode?, forcedID: Int = -1,
factory: ((Path, NodeConfiguration, network: MockNetwork, LegallyIdentifiableNode?) -> MockNode)? = null): MockNode {
fun createNode(withTimestamper: LegallyIdentifiableNode?, forcedID: Int = -1, nodeFactory: Factory = defaultFactory): MockNode {
val newNode = forcedID == -1
val id = if (newNode) counter++ else forcedID
@ -88,9 +106,9 @@ class MockNetwork(private val threadPerNode: Boolean = false) {
val config = object : NodeConfiguration {
override val myLegalName: String = "Mock Company $id"
override val exportJMXto: String = ""
override val nearestCity: String = "Atlantis"
}
val fac = factory ?: { p, n, n2, l -> MockNode(p, n, n2, l, id) }
val node = fac(path, config, this, withTimestamper).start()
val node = nodeFactory.create(path, config, this, withTimestamper).start()
_nodes.add(node)
return node
}
@ -112,8 +130,10 @@ class MockNetwork(private val threadPerNode: Boolean = false) {
/**
* Sets up a two node network in which the first node runs a timestamping service and the other doesn't.
*/
fun createTwoNodes(factory: ((Path, NodeConfiguration, network: MockNetwork, LegallyIdentifiableNode?) -> MockNode)? = null): Pair<MockNode, MockNode> {
fun createTwoNodes(nodeFactory: Factory = defaultFactory): Pair<MockNode, MockNode> {
require(nodes.isEmpty())
return Pair(createNode(null, -1, factory), createNode(nodes[0].legallyIdentifableAddress, -1, factory))
return Pair(createNode(null, -1, nodeFactory), createNode(nodes[0].legallyIdentifiableAddress, -1, nodeFactory))
}
fun addressToNode(address: SingleMessageRecipient): MockNode = nodes.single { it.net.myAddress == address }
}

View File

@ -0,0 +1,34 @@
package demos
import java.time.*
import javax.annotation.concurrent.ThreadSafe
/**
* A [Clock] that can have the date advanced for use in demos
*/
@ThreadSafe
class DemoClock(private var delegateClock: Clock = Clock.systemUTC()) : Clock() {
@Synchronized fun updateDate(date: LocalDate): Boolean {
val currentDate = LocalDate.now(this)
if(currentDate.isBefore(date)) {
// It's ok to increment
delegateClock = Clock.offset(delegateClock, Duration.between(currentDate.atStartOfDay(),date.atStartOfDay()))
return true
}
return false
}
@Synchronized override fun instant(): Instant {
return delegateClock.instant()
}
@Synchronized override fun withZone(zone: ZoneId): Clock {
return DemoClock(delegateClock.withZone(zone))
}
@Synchronized override fun getZone(): ZoneId {
return delegateClock.zone
}
}

View File

@ -10,10 +10,10 @@ package demos
import contracts.Cash
import core.*
import core.messaging.LegallyIdentifiableNode
import core.node.Node
import core.node.NodeConfiguration
import core.node.services.ArtemisMessagingService
import core.node.services.LegallyIdentifiableNode
import core.node.services.NodeInterestRates
import core.serialization.deserialize
import core.utilities.ANSIProgressRenderer
@ -71,6 +71,7 @@ fun main(args: Array<String>) {
val config = object : NodeConfiguration {
override val myLegalName: String = "Rate fix demo node"
override val exportJMXto: String = "http"
override val nearestCity: String = "Atlantis"
}
val node = logElapsedTime("Node startup") { Node(dir, myNetAddr, config, null).start() }

View File

@ -15,12 +15,12 @@ import contracts.CommercialPaper
import core.*
import core.crypto.SecureHash
import core.crypto.generateKeyPair
import core.messaging.LegallyIdentifiableNode
import core.messaging.SingleMessageRecipient
import core.node.Node
import core.node.NodeConfiguration
import core.node.NodeConfigurationFromConfig
import core.node.services.ArtemisMessagingService
import core.node.services.LegallyIdentifiableNode
import core.node.services.NodeAttachmentService
import core.node.services.NodeWalletService
import core.protocols.ProtocolLogic

View File

@ -11,7 +11,7 @@ package protocols
import co.paralleluniverse.fibers.Suspendable
import core.*
import core.crypto.DigitalSignature
import core.messaging.LegallyIdentifiableNode
import core.node.services.LegallyIdentifiableNode
import core.messaging.SingleMessageRecipient
import core.protocols.ProtocolLogic
import core.utilities.ProgressTracker
@ -50,10 +50,13 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder,
@Suspendable
override fun call() {
progressTracker.currentStep = progressTracker.steps[0]
val fix = query()
progressTracker.currentStep = WORKING
checkFixIsNearExpected(fix)
tx.addCommand(fix, oracle.identity.owningKey)
beforeSigning(fix)
progressTracker.currentStep = SIGNING
tx.addSignatureUnchecked(sign())
}

View File

@ -12,7 +12,7 @@ import co.paralleluniverse.fibers.Suspendable
import core.Party
import core.WireTransaction
import core.crypto.DigitalSignature
import core.messaging.LegallyIdentifiableNode
import core.node.services.LegallyIdentifiableNode
import core.messaging.MessageRecipients
import core.messaging.StateMachineManager
import core.node.services.NodeTimestamperService
@ -20,6 +20,7 @@ import core.node.services.TimestamperService
import core.protocols.ProtocolLogic
import core.random63BitValue
import core.serialization.SerializedBytes
import core.utilities.ProgressTracker
/**
* The TimestampingProtocol class is the client code that talks to a [NodeTimestamperService] on some remote node. It is a
@ -31,7 +32,8 @@ import core.serialization.SerializedBytes
* a network message: use it only from spare application threads that don't have to respond to anything.
*/
class TimestampingProtocol(private val node: LegallyIdentifiableNode,
private val wtxBytes: SerializedBytes<WireTransaction>) : ProtocolLogic<DigitalSignature.LegallyIdentifiable>() {
private val wtxBytes: SerializedBytes<WireTransaction>,
override val progressTracker: ProgressTracker = TimestampingProtocol.tracker()) : ProtocolLogic<DigitalSignature.LegallyIdentifiable>() {
class Client(private val stateMachineManager: StateMachineManager, private val node: LegallyIdentifiableNode) : TimestamperService {
override val identity: Party = node.identity
@ -41,9 +43,18 @@ class TimestampingProtocol(private val node: LegallyIdentifiableNode,
}
}
companion object {
object REQUESTING : ProgressTracker.Step("Requesting signature by timestamping service")
object VALIDATING : ProgressTracker.Step("Validating received signature from timestamping service")
fun tracker() = ProgressTracker(REQUESTING, VALIDATING)
}
@Suspendable
override fun call(): DigitalSignature.LegallyIdentifiable {
progressTracker.currentStep = REQUESTING
val sessionID = random63BitValue()
val replyTopic = "${NodeTimestamperService.TIMESTAMPING_PROTOCOL_TOPIC}.$sessionID"
val req = Request(wtxBytes, serviceHub.networkService.myAddress, replyTopic)
@ -52,6 +63,7 @@ class TimestampingProtocol(private val node: LegallyIdentifiableNode,
NodeTimestamperService.TIMESTAMPING_PROTOCOL_TOPIC, node.address, 0, sessionID, req)
// Check that the timestamping authority gave us back a valid signature and didn't break somehow
progressTracker.currentStep = VALIDATING
maybeSignature.validate { sig ->
sig.verifyWithECDSA(wtxBytes)
return sig

View File

@ -15,7 +15,7 @@ import contracts.sumCashBy
import core.*
import core.crypto.DigitalSignature
import core.crypto.signWithECDSA
import core.messaging.LegallyIdentifiableNode
import core.node.services.LegallyIdentifiableNode
import core.messaging.SingleMessageRecipient
import core.messaging.StateMachineManager
import protocols.TimestampingProtocol

View File

@ -0,0 +1,756 @@
# name longitude latitude
Shanghai 121.47 31.23
Bombay 72.82 18.96
Karachi 67.01 24.86
Buenos Aires -58.37 -34.61
Delhi 77.21 28.67
Istanbul 29 41.1
Manila 120.97 14.62
Sao Paulo -46.63 -23.53
Moscow 37.62 55.75
Dhaka 90.39 23.7
Soul 126.99 37.56
Lagos 3.35 6.5
Kinshasa 15.32 -4.31
Tokyo 139.77 35.67
Mexico City -99.14 19.43
Jakarta 106.83 -6.18
New York -73.94 40.67
Tehran 51.43 35.67
Cairo 31.25 30.06
Lima -77.05 -12.07
Peking 116.4 39.93
London -0.1 51.52
Bogota -74.09 4.63
Lahore 74.35 31.56
Rio de Janeiro -43.2 -22.91
Bangkok 100.5 13.73
Bagdad 44.44 33.33
Bangalore 77.56 12.97
Santiago -70.64 -33.46
Calcutta 88.36 22.57
Singapore 103.85 1.3
Toronto -79.38 43.65
Rangoon 96.15 16.79
Ibadan 3.93 7.38
Riyadh 46.77 24.65
Madras 80.27 13.09
Chongqing 106.58 29.57
Ho Chi Minh City 106.69 10.78
Xian 108.9 34.27
Wuhan 114.27 30.58
Alexandria 29.95 31.22
Saint Petersburg 30.32 59.93
Hyderabad 78.48 17.4
Chengdu 104.07 30.67
Abidjan -4.03 5.33
Ankara 32.85 39.93
Ahmadabad 72.58 23.03
Los Angeles -118.41 34.11
Tianjin 117.2 39.13
Chattagam 91.81 22.33
Sydney 151.21 -33.87
Yokohama 139.62 35.47
Melbourne 144.96 -37.81
Shenyang 123.45 41.8
Cape Town 18.46 -33.93
Berlin 13.38 52.52
Pusan 129.03 35.11
Montreal -73.57 45.52
Harbin 126.65 45.75
Durban 30.99 -29.87
Gizeh 31.21 30.01
Nanjing 118.78 32.05
Casablanca -7.62 33.6
Pune 73.84 18.53
Addis Abeba 38.74 9.03
Pyongyang 125.75 39.02
Surat 72.82 21.2
Madrid -3.71 40.42
Guangzhou 113.25 23.12
Jiddah 39.17 21.5
Kanpur 80.33 26.47
Nairobi 36.82 -1.29
Jaipur 75.8 26.92
Dar es Salaam 39.28 -6.82
Salvador -38.5 -12.97
Chicago -87.68 41.84
Taiyuan 112.55 37.87
al-Mawsil 43.14 36.34
Faisalabad 73.11 31.41
Changchun 125.35 43.87
Izmir 27.15 38.43
Taibei 121.45 25.02
Osaka 135.5 34.68
Lakhnau 80.92 26.85
Kiev 30.52 50.43
Luanda 13.24 -8.82
Inchon 126.64 37.48
Rome 12.5 41.89
Dakar -17.48 14.72
Belo Horizonte -43.94 -19.92
Fortaleza -38.59 -3.78
Mashhad 59.57 36.27
Maracaibo -71.66 10.73
Kabul 69.17 34.53
Santo Domingo -69.91 18.48
Taegu 128.6 35.87
Brasilia -47.91 -15.78
Umm Durman 32.48 15.65
Nagpur 79.08 21.16
Surabaya 112.74 -7.24
Kano 8.52 12
Medellin -75.54 6.29
Accra -0.2 5.56
Nagoya 136.91 35.15
Benin 5.62 6.34
Shijiazhuang 114.48 38.05
Guayaquil -79.9 -2.21
Changsha 112.97 28.2
Houston -95.39 29.77
Khartoum 32.52 15.58
Paris 2.34 48.86
Cali -76.52 3.44
Algiers 3.04 36.77
Jinan 117 36.67
Havanna -82.39 23.13
Tashkent 69.3 41.31
Dalian 121.65 38.92
Jilin 126.55 43.85
Nanchang 115.88 28.68
Zhengzhou 113.67 34.75
Vancouver -123.13 49.28
Johannesburg 28.04 -26.19
Bayrut 35.5 33.89
Douala 9.71 4.06
Jiulong 114.17 22.32
Caracas -66.93 10.54
Kaduna 7.44 10.52
Bucharest 26.1 44.44
Ecatepec -99.05 19.6
Sapporo 141.34 43.06
Port Harcourt 7.01 4.81
Hangzhou 120.17 30.25
Rawalpindi 73.04 33.6
San'a 44.21 15.38
Conakry -13.67 9.55
Curitiba -49.29 -25.42
al-Basrah 47.82 30.53
Brisbane 153.02 -27.46
Xinyang 114.07 32.13
Medan 98.67 3.59
Indore 75.86 22.72
Manaus -60.02 -3.12
Kumasi -1.63 6.69
Hamburg 10 53.55
Rabat -6.84 34.02
Minsk 27.55 53.91
Patna 85.13 25.62
Valencia -67.98 10.23
Bhopal 77.4 23.24
Soweto 27.84 -26.28
Warsaw 21.02 52.26
Qingdao 120.32 36.07
Vienna 16.37 48.22
Yaounde 11.52 3.87
Dubai 55.33 25.27
Thana 72.97 19.2
Aleppo 37.17 36.23
Bekasi 106.97 -6.22
Budapest 19.08 47.51
Bamako -7.99 12.65
Ludhiana 75.84 30.91
Harare 31.05 -17.82
Esfahan 51.68 32.68
Pretoria 28.22 -25.73
Barcelona 2.17 41.4
Lubumbashi 27.48 -11.66
Bandung 107.6 -6.91
Guadalajara -103.35 20.67
Tangshan 118.19 39.62
Muqdisho 45.33 2.05
Phoenix -112.07 33.54
Damascus 36.32 33.5
Quito -78.5 -0.19
Agra 78.01 27.19
Urumqi 87.58 43.8
Davao 125.63 7.11
Santa Cruz -63.21 -17.77
Antananarivo 47.51 -18.89
Kobe 135.17 34.68
Juarez -106.49 31.74
Tijuana -117.02 32.53
Recife -34.92 -8.08
Multan 71.45 30.2
Ha Noi 105.84 21.03
Gaoxiong 120.27 22.63
Belem -48.5 -1.44
Cordoba -64.19 -31.4
Kampala 32.58 0.32
Lome 1.35 6.17
Hyderabad 68.37 25.38
Suzhou 120.62 31.3
Vadodara 73.18 22.31
Gujranwala 74.18 32.16
Bursa 29.08 40.2
Mbuji-Mayi 23.59 -6.13
Pimpri 73.8 18.62
Karaj 50.97 35.8
Kyoto 135.75 35.01
Tangerang 106.63 -6.18
Aba 7.35 5.1
Kharkiv 36.22 49.98
Puebla -98.22 19.05
Nashik 73.78 20.01
Kuala Lumpur 101.71 3.16
Philadelphia -75.13 40.01
Fukuoka 130.41 33.59
Taejon 127.43 36.33
Lanzhou 103.68 36.05
Mecca 39.82 21.43
Shantou 116.67 23.37
Koyang 126.93 37.7
Hefei 117.28 31.85
Novosibirsk 82.93 55.04
Porto Alegre -51.22 -30.04
Adana 35.32 37
Makasar 119.41 -5.14
Tabriz 46.3 38.08
Narayanganj 90.5 23.62
Faridabad 77.3 28.38
Fushun 123.88 41.87
Phnum Penh 104.92 11.57
Luoyang 112.47 34.68
Khulna 89.56 22.84
Depok 106.83 -6.39
Lusaka 28.29 -15.42
Ghaziabad 77.41 28.66
Handan 114.48 36.58
San Antonio -98.51 29.46
Kawasaki 139.7 35.53
Kwangju 126.91 35.16
Peshawar 71.54 34.01
Rajkot 70.79 22.31
Suwon 127.01 37.26
Mandalay 96.09 21.98
Almaty 76.92 43.32
Munich 11.58 48.14
Mirat 77.7 28.99
Baotou 110.05 40.6
Milan 9.19 45.48
Rongcheng 116.34 23.54
Kalyan 73.16 19.25
Montevideo -56.17 -34.87
Xianggangdao 114.14 22.27
Yekaterinburg 60.6 56.85
Ouagadougou -1.53 12.37
Guarulhos -46.49 -23.46
Semarang 110.42 -6.97
Xuzhou 117.18 34.27
Perth 115.84 -31.96
Dallas -96.77 32.79
Stockholm 18.07 59.33
Palembang 104.75 -2.99
San Diego -117.14 32.81
Goiania -49.26 -16.72
Gaziantep 37.39 37.07
Nizhniy Novgorod 44 56.33
Shiraz 52.57 29.63
Rosario -60.67 -32.94
Fuzhou 119.3 26.08
Nezahualcoyotl -99.03 19.41
Saitama 139.64 35.87
Shenzhen 114.13 22.53
Yerevan 44.52 40.17
Tripoli 13.18 32.87
Anshan 122.95 41.12
Varanasi 83.01 25.32
Guiyang 106.72 26.58
Baku 49.86 40.39
Wuxi 120.3 31.58
Prague 14.43 50.08
Brazzaville 15.26 -4.25
Subang Jaya 101.53 3.15
Leon -101.69 21.12
Hiroshima 132.44 34.39
Amritsar 74.87 31.64
Huainan 116.98 32.63
Barranquilla -74.8 10.96
Monrovia -10.8 6.31
'Amman 35.93 31.95
Tbilisi 44.79 41.72
Abuja 7.49 9.06
Aurangabad 75.32 19.89
Sofia 23.31 42.69
Omsk 73.4 55
Monterrey -100.32 25.67
Port Elizabeth 25.59 -33.96
Navi Mumbai 73.06 19.11
Maputo 32.57 -25.95
Allahabad 81.84 25.45
Samara 50.15 53.2
Belgrade 20.5 44.83
Campinas -47.08 -22.91
Sholapur 75.89 17.67
Kazan 49.13 55.75
Irbil 44.01 36.18
Barquisimeto -69.3 10.05
K?benhavn 12.58 55.67
Xianyang 108.7 34.37
Baoding 115.48 38.87
Guatemala -90.55 14.63
Maceio -35.75 -9.65
Nova Iguacu -43.47 -22.74
Kunming 102.7 25.05
Taizhong 120.68 24.15
Maiduguri 13.16 11.85
Datong 113.3 40.08
Dublin -6.25 53.33
Jabalpur 79.94 23.17
Visakhapatnam 83.3 17.73
Rostov-na-Donu 39.71 47.24
Dnipropetrovs'k 34.98 48.45
Shubra-El-Khema 31.25 30.11
Srinagar 74.79 34.09
Benxi 123.75 41.33
Brussels 4.33 50.83
al-Madinah 39.59 24.48
Adelaide 138.6 -34.93
Zapopan -103.4 20.72
Chelyabinsk 61.43 55.15
Haora 88.33 22.58
Calgary -114.06 51.05
Sendai 140.89 38.26
Tegucigalpa -87.22 14.09
Ranchi 85.33 23.36
Songnam 127.15 37.44
Ilorin 4.55 8.49
Fez -5 34.05
Ufa 56.04 54.78
Klang 101.45 3.04
Chandigarh 76.78 30.75
Ahvaz 48.72 31.28
Koyampattur 76.96 11.01
Cologne 6.97 50.95
Qom 50.95 34.65
Odesa 30.73 46.47
Donetsk 37.82 48
Jodhpur 73.02 26.29
Sao Luis -44.3 -2.5
Sao Goncalo -43.07 -22.84
Kitakyushu 130.86 33.88
Huaibei 116.75 33.95
Perm 56.25 58
Changzhou 119.97 31.78
Maisuru 76.65 12.31
Guwahati 91.75 26.19
Volgograd 44.48 48.71
Konya 32.48 37.88
Naples 14.27 40.85
Vijayawada 80.63 16.52
Ulsan 129.31 35.55
San Jose -121.85 37.3
Birmingham -1.91 52.48
Chiba 140.11 35.61
Ciudad Guayana -62.62 8.37
Kolwezi 25.66 -10.7
Padang 100.35 -0.95
Managua -86.27 12.15
Mendoza -68.83 -32.89
Gwalior 78.17 26.23
Biskek 74.57 42.87
Kathmandu 85.31 27.71
El Alto -68.17 -16.5
Niamey 2.12 13.52
Kigali 30.06 -1.94
Qiqihar 124 47.35
Ulaanbaatar 106.91 47.93
Krasnoyarsk 93.06 56.02
Madurai 78.12 9.92
Edmonton -113.54 53.57
Asgabat 58.38 37.95
al-H?artum Bah?ri 32.52 15.64
Arequipa -71.53 -16.39
Marrakesh -8 31.63
Bandar Lampung 105.27 -5.44
Pingdingshan 113.3 33.73
Cartagena -75.5 10.4
Hubli 75.13 15.36
La Paz -68.15 -16.5
Wenzhou 120.65 28.02
Ottawa -75.71 45.42
Johor Bahru 103.75 1.48
Mombasa 39.66 -4.04
Lilongwe 33.8 -13.97
Turin 7.68 45.08
Duque de Caxias -43.31 -22.77
Abu Dhabi 54.37 24.48
Jalandhar 75.57 31.33
Warri 5.76 5.52
Valencia -0.39 39.48
Oslo 10.75 59.91
Taian 117.12 36.2
ad-Dammam 50.1 26.43
Mira Bhayandar 72.85 19.29
Salem 78.16 11.67
Pietermaritzburg 30.39 -29.61
Naucalpan -99.23 19.48
H?ims 36.72 34.73
Bhubaneswar 85.84 20.27
Hamamatsu 137.73 34.72
Saratov 46.03 51.57
Detroit -83.1 42.38
Kirkuk 44.39 35.47
Sakai 135.48 34.57
Onitsha 6.78 6.14
Quetta 67.02 30.21
Aligarh 78.06 27.89
Voronezh 39.26 51.72
Freetown -13.24 8.49
Tucuman -65.22 -26.83
Bogor 106.79 -6.58
Niigata 139.04 37.92
Thiruvananthapuram 76.95 8.51
Jacksonville -81.66 30.33
Bareli 79.41 28.36
Cebu 123.9 10.32
Kota 75.83 25.18
Natal -35.22 -5.8
Shihung 126.89 37.46
Puchon 126.77 37.48
Tiruchchirappalli 78.69 10.81
Trujillo -79.03 -8.11
Sharjah 55.41 25.37
Kermanshah 47.06 34.38
Qinhuangdao 119.62 39.93
Anyang 114.35 36.08
Bhiwandi 73.05 19.3
an-Najaf 44.34 32
Sao Bernardo do Campo -46.54 -23.71
Teresina -42.8 -5.1
Nanning 108.32 22.82
Antalya 30.71 36.89
Campo Grande -54.63 -20.45
Indianapolis -86.15 39.78
Jaboatao -35.02 -8.11
Zaporizhzhya 35.17 47.85
Hohhot 111.64 40.82
Marseille 5.37 43.31
Moradabad 78.76 28.84
Zhangjiakou 114.93 40.83
Liuzhou 109.25 24.28
Nouakchott -15.98 18.09
Rajshahi 88.59 24.37
Yantai 121.4 37.53
Tainan 120.19 23
Xining 101.77 36.62
Port-au-Prince -72.34 18.54
Hegang 130.37 47.4
Akure 5.19 7.25
N'Djamena 15.05 12.11
Guadalupe -100.26 25.68
Cracow 19.96 50.06
Malang 112.62 -7.98
Hengyang 112.62 26.89
Athens 23.73 37.98
Puyang 114.98 35.7
San Francisco -122.45 37.77
Jerusalem 35.22 31.78
Amsterdam 4.89 52.37
?odz 19.46 51.77
Merida -89.62 20.97
Austin -97.75 30.31
Abeokuta 3.35 7.16
Xinxiang 113.87 35.32
Raipur 81.63 21.24
Tunis 10.22 36.84
Columbus -82.99 39.99
Chihuahua -106.08 28.63
L'viv 24 49.83
Cotonou 2.44 6.36
Pekan Baru 101.43 0.56
Blantyre 34.99 -15.79
La Plata -57.96 -34.92
Bulawayo 28.58 -20.17
Tangier -5.81 35.79
Kayseri 35.48 38.74
Tolyatti 49.51 53.48
Foshan 113.12 23.03
Ningbo 121.55 29.88
Langfang 116.68 39.52
Ampang Jaya 101.77 3.15
Liaoyang 123.18 41.28
Riga 24.13 56.97
Changzhi 111.75 35.22
Kryvyy Rih 33.35 47.92
Libreville 9.45 0.39
Chonju 127.14 35.83
Fort Worth -97.34 32.75
as-Sulaymaniyah 45.43 35.56
Osasco -46.78 -23.53
Zamboanga 122.08 6.92
Tlalnepantla -99.19 19.54
Gorakhpur 83.36 26.76
San Luis Potosi -100.98 22.16
Sevilla -5.98 37.4
Zhuzhou 113.15 27.83
Zagreb 15.97 45.8
Huangshi 115.1 30.22
Puente Alto -70.57 -33.61
Shaoguan 113.58 24.8
Matola 32.46 -25.97
Guilin 110.28 25.28
Aguascalientes -102.3 21.88
Shizuoka 138.39 34.98
Benghazi 20.07 32.12
Fuxin 121.65 42.01
Joao Pessoa -34.86 -7.12
Ipoh 101.07 4.6
Contagem -44.1 -19.91
Dushanbe 68.78 38.57
Zhanjiang 110.38 21.2
Xingtai 114.49 37.07
Okayama 133.92 34.67
Yogyakarta 110.37 -7.78
Bhilai 81.38 21.21
Zigong 104.78 29.4
Mudanjiang 129.6 44.58
Wahran -0.62 35.7
Enugu 7.51 6.44
Santo Andre -46.53 -23.65
Colombo 79.85 6.93
Chimalhuacan -98.96 19.44
Shatian 114.19 22.38
Memphis -90.01 35.11
Kumamoto 130.71 32.8
Sao Jose dos Campos -45.88 -23.2
Zhangdian 118.06 36.8
Acapulco -99.92 16.85
Xiangtan 112.9 27.85
Quebec -71.23 46.82
Dasmarinas 120.93 14.33
Zaria 7.71 11.08
Nantong 120.82 32.02
Charlotte -80.83 35.2
Pointe Noire 11.87 -4.77
Shaoyang 111.2 27
Queretaro -100.4 20.59
Hamilton -79.85 43.26
Islamabad 73.06 33.72
Panjin 122.05 41.18
Saltillo -101 25.42
Ansan 126.86 37.35
Jamshedpur 86.2 22.79
Zaragoza -0.89 41.65
Cancun -86.83 21.17
Dandong 124.4 40.13
Frankfurt 8.68 50.12
Palermo 13.36 38.12
Haikou 110.32 20.05
'Adan 45.03 12.79
Amravati 77.76 20.95
Winnipeg -97.17 49.88
Sagamihara 139.38 35.58
Zhangzhou 117.67 24.52
Gazzah 34.44 31.53
Kataka 85.88 20.47
El Paso -106.44 31.85
Krasnodar 38.98 45.03
Kuching 110.34 1.55
Wroc?aw 17.03 51.11
Asmara 38.94 15.33
Zhenjiang 119.43 32.22
Baltimore -76.61 39.3
Benoni 28.33 -26.15
Mersin 34.63 36.81
Izhevsk 53.23 56.85
Yancheng 120.12 33.39
Hermosillo -110.97 29.07
Yuanlong 114.02 22.44
Uberlandia -48.28 -18.9
Ulyanovsk 48.4 54.33
Bouake -5.03 7.69
Santiago -70.69 19.48
Mexicali -115.47 32.65
Hai Phong 106.68 20.86
Anyang 126.92 37.39
Dadiangas 125.25 6.1
Morelia -101.18 19.72
Oshogbo 4.56 7.77
Chongju 127.5 36.64
Jos 8.89 9.93
al-'Ayn 55.74 24.23
Sorocaba -47.47 -23.49
Bikaner 73.32 28.03
Taizhou 119.9 32.49
Antipolo 121.18 14.59
Xiamen 118.08 24.45
Cochabamba -66.17 -17.38
Culiacan -107.39 24.8
Yingkou 122.28 40.67
Kagoshima 130.56 31.59
Siping 124.33 43.17
Orumiyeh 45 37.53
Luancheng 114.65 37.88
Diyarbak?r 40.23 37.92
Yaroslavl 39.87 57.62
Mixco -90.6 14.64
Banjarmasin 114.59 -3.33
Chisinau 28.83 47.03
Djibouti 43.15 11.59
Seattle -122.35 47.62
Stuttgart 9.19 48.79
Khabarovsk 135.12 48.42
Rotterdam 4.48 51.93
Jinzhou 121.1 41.12
Kisangani 25.19 0.53
San Pedro Sula -88.03 15.47
Bengbu 117.33 32.95
Irkutsk 104.24 52.33
Shihezi 86.03 44.3
Maracay -67.47 10.33
Cucuta -72.51 7.88
Bhavnagar 72.13 21.79
Port Said 32.29 31.26
Denver -104.87 39.77
Genoa 8.93 44.42
Jiangmen 113.08 22.58
Dortmund 7.48 51.51
Barnaul 83.75 53.36
Washington -77.02 38.91
Veracruz -96.14 19.19
Ribeirao Preto -47.8 -21.17
Vladivostok 131.9 43.13
Mar del Plata -57.58 -38
Boston -71.02 42.34
Eskisehir 30.52 39.79
Warangal 79.58 18.01
Zahedan 60.83 29.5
Essen 7 51.47
Dusseldorf 6.79 51.24
Kaifeng 114.35 34.85
Kingston -76.8 17.99
Glasgow -4.27 55.87
Funabashi 139.99 35.7
Shah Alam 101.56 3.07
Maoming 110.87 21.92
Hachioji 139.33 35.66
Meknes -5.56 33.9
Hamhung 127.54 39.91
Villa Nueva -90.59 14.53
Sargodha 72.67 32.08
Las Vegas -115.22 36.21
Resht 49.63 37.3
Cangzhou 116.87 38.32
Tanggu 117.67 39
Helsinki 24.94 60.17
Malaga -4.42 36.72
Milwaukee -87.97 43.06
Nashville -86.78 36.17
Ife 4.56 7.48
Changde 111.68 29.03
at-Ta'if 40.38 21.26
Surakarta 110.82 -7.57
Poznan 16.9 52.4
Barcelona -64.72 10.13
Bloemfontein 26.23 -29.15
Lopez Mateos -99.26 19.57
Bangui 18.56 4.36
Reynosa -98.28 26.08
Xigong 114.25 22.33
Cuiaba -56.09 -15.61
Shiliguri 88.42 26.73
Oklahoma City -97.51 35.47
Louisville -85.74 38.22
Jiamusi 130.35 46.83
Huaiyin 119.03 33.58
Welkom 26.73 -27.97
Kolhapur 74.22 16.7
Ulhasnagar 73.15 19.23
Rajpur 88.44 22.44
Bremen 8.81 53.08
San Salvador -89.19 13.69
Maanshan 118.48 31.73
Tembisa 28.22 -25.99
Banqiao 121.44 25.02
Toluca -99.67 19.29
Portland -122.66 45.54
Gold Coast 153.44 -28.07
Kota Kinabalu 116.07 5.97
Vilnius 25.27 54.7
Agadir -9.61 30.42
Ajmer 74.64 26.45
Orenburg 55.1 51.78
Neijiang 105.05 29.58
Salta -65.41 -24.79
Guntur 80.44 16.31
Novokuznetsk 87.1 53.75
Yangzhou 119.43 32.4
Durgapur 87.31 23.5
Shashi 112.23 30.32
Asuncion -57.63 -25.3
Aparecida de Goiania -49.24 -16.82
Ribeirao das Neves -44.08 -19.76
Petaling Jaya 101.62 3.1
Sangli-Miraj 74.57 16.86
Dehra Dun 78.05 30.34
Maturin -63.17 9.75
Torreon -103.43 25.55
Jiaozuo 113.22 35.25
Zhuhai 113.57 22.28
Nanded 77.29 19.17
Suez 32.54 29.98
Tyumen 65.53 57.15
Albuquerque -106.62 35.12
Cagayan 124.67 8.45
Mwanza 32.89 -2.52
Petare -66.83 10.52
Soledad -74.77 10.92
Uijongbu 127.04 37.74
Yueyang 113.1 29.38
Feira de Santana -38.97 -12.25
Ta'izz 44.04 13.6
Tucson -110.89 32.2
Naberezhnyye Chelny 52.32 55.69
Kerman 57.08 30.3
Matsuyama 132.77 33.84
Garoua 13.39 9.3
Tlaquepaque -103.32 20.64
Tuxtla Gutierrez -93.12 16.75
Jamnagar 70.07 22.47
Jammu 74.85 32.71
Gulbarga 76.82 17.34
Chiclayo -79.84 -6.76
Hanover 9.73 52.4
Bucaramanga -73.13 7.13
Bahawalpur 71.67 29.39
Goteborg 12.01 57.72
Zhunmen 113.98 22.41
Bhatpara 88.42 22.89
Ryazan 39.74 54.62
Calamba 121.15 14.21
Changwon 128.62 35.27
Aracaju -37.07 -10.91
Zunyi 106.92 27.7
Lipetsk 39.62 52.62
Dresden 13.74 51.05
Saharanpur 77.54 29.97
H?amah 36.73 35.15
Niyala 24.89 12.06
San Nicolas de los Garza -100.3 25.75
Higashiosaka 135.59 34.67
al-H?illah 44.43 32.48
Leipzig 12.4 51.35
Xuchang 113.82 34.02
Wuhu 118.37 31.35
Boma 13.05 -5.85
Kananga 22.4 -5.89
Mykolayiv 32 46.97
Atlanta -84.42 33.76
Londrina -51.18 -23.3
Tabuk 36.57 28.39
Cuautitlan Izcalli -99.25 19.65
Nuremberg 11.05 49.45
Santa Fe -60.69 -31.6
Joinville -48.84 -26.32
Zurich 8.55 47.36

View File

@ -1,2 +1,3 @@
myLegalName = "Vast Global MegaCorp, Ltd"
exportJMXto = "http"
exportJMXto = "http"
nearestCity = "The Moon"

View File

@ -74,11 +74,11 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
//expression = "( fixedLeg.notional * (fixedLeg.fixedRate)) - (floatingLeg.notional * (rateSchedule.get(context.getDate('currentDate'))))",
// How it's ended up looking, which I think is now broken but it's a WIP.
expression = InterestRateSwap.Expression("( fixedLeg.notional.pennies * (fixedLeg.fixedRate.ratioUnit.value)) -" +
expression = Expression("( fixedLeg.notional.pennies * (fixedLeg.fixedRate.ratioUnit.value)) -" +
"(floatingLeg.notional.pennies * (calculation.fixingSchedule.get(context.getDate('currentDate')).rate.ratioUnit.value))"),
floatingLegPaymentSchedule = HashMap(),
fixedLegpaymentSchedule = HashMap()
fixedLegPaymentSchedule = HashMap()
)
val EUR = currency("EUR")
@ -94,13 +94,13 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
valuationDate = "Every Local Business Day",
notificationTime = "2:00pm London",
resolutionTime = "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given ",
interestRate = OracleRetrievableReferenceRate(TelerateOracle("T3270"), Tenor("6M"), "EONIA"),
interestRate = ReferenceRate("T3270", Tenor("6M"), "EONIA"),
addressForTransfers = "",
exposure = UnknownType(),
localBusinessDay = BusinessCalendar.getInstance("London"),
tradeID = "trade1",
hashLegalDocs = "put hash here",
dailyInterestAmount = InterestRateSwap.Expression("(CashAmount * InterestRate ) / (fixedLeg.notional.currency.currencyCode.equals('GBP')) ? 365 : 360")
dailyInterestAmount = Expression("(CashAmount * InterestRate ) / (fixedLeg.notional.currency.currencyCode.equals('GBP')) ? 365 : 360")
)
InterestRateSwap.State(fixedLeg = fixedLeg, floatingLeg = floatingLeg, calculation = calculation, common = common)
@ -165,11 +165,11 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
//expression = "( fixedLeg.notional * (fixedLeg.fixedRate)) - (floatingLeg.notional * (rateSchedule.get(context.getDate('currentDate'))))",
// How it's ended up looking, which I think is now broken but it's a WIP.
expression = InterestRateSwap.Expression("( fixedLeg.notional.pennies * (fixedLeg.fixedRate.ratioUnit.value)) -" +
expression = Expression("( fixedLeg.notional.pennies * (fixedLeg.fixedRate.ratioUnit.value)) -" +
"(floatingLeg.notional.pennies * (calculation.fixingSchedule.get(context.getDate('currentDate')).rate.ratioUnit.value))"),
floatingLegPaymentSchedule = HashMap(),
fixedLegpaymentSchedule = HashMap()
fixedLegPaymentSchedule = HashMap()
)
val EUR = currency("EUR")
@ -185,13 +185,13 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
valuationDate = "Every Local Business Day",
notificationTime = "2:00pm London",
resolutionTime = "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given ",
interestRate = OracleRetrievableReferenceRate(TelerateOracle("T3270"), Tenor("6M"), "EONIA"),
interestRate = ReferenceRate("T3270", Tenor("6M"), "EONIA"),
addressForTransfers = "",
exposure = UnknownType(),
localBusinessDay = BusinessCalendar.getInstance("London"),
tradeID = "trade1",
hashLegalDocs = "put hash here",
dailyInterestAmount = InterestRateSwap.Expression("(CashAmount * InterestRate ) / (fixedLeg.notional.currency.currencyCode.equals('GBP')) ? 365 : 360")
dailyInterestAmount = Expression("(CashAmount * InterestRate ) / (fixedLeg.notional.currency.currencyCode.equals('GBP')) ? 365 : 360")
)
return InterestRateSwap.State(fixedLeg = fixedLeg, floatingLeg = floatingLeg, calculation = calculation, common = common)
@ -335,12 +335,6 @@ class IRSTests {
// TODO: r1*r2 ?
}
@Test
fun `reference rate testing`() {
val r1 = TestReferenceRate("5")
assert(100 * r1.getAsOf(null) == 5)
}
@Test
fun `expression calculation testing`() {
val dummyIRS = singleIRS()
@ -366,7 +360,7 @@ class IRSTests {
for (i in stuffToPrint) {
println(i)
var z = dummyIRS.evaluateCalculation(LocalDate.of(2016, 9, 12), InterestRateSwap.Expression(i))
var z = dummyIRS.evaluateCalculation(LocalDate.of(2016, 9, 12), Expression(i))
println(z.javaClass)
println(z)
println("-----------")

View File

@ -11,8 +11,8 @@ package core
import com.codahale.metrics.MetricRegistry
import core.crypto.*
import core.messaging.MessagingService
import core.messaging.MockNetworkMapService
import core.messaging.NetworkMapService
import core.node.services.MockNetworkMapService
import core.node.services.NetworkMapService
import core.node.services.*
import core.serialization.SerializedBytes
import core.serialization.deserialize

View File

@ -8,22 +8,25 @@
package core.messaging
import protocols.FetchAttachmentsProtocol
import protocols.FetchDataProtocol
import core.Attachment
import core.crypto.SecureHash
import core.crypto.sha256
import core.testing.MockNetwork
import core.node.NodeConfiguration
import core.node.services.LegallyIdentifiableNode
import core.node.services.NodeAttachmentService
import core.serialization.OpaqueBytes
import core.testing.MockNetwork
import core.testutils.rootCauseExceptions
import core.utilities.BriefLogFormatter
import org.junit.Before
import org.junit.Test
import protocols.FetchAttachmentsProtocol
import protocols.FetchDataProtocol
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardOpenOption
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry
@ -90,16 +93,18 @@ class AttachmentTests {
@Test
fun maliciousResponse() {
// Make a node that doesn't do sanity checking at load time.
val n0 = network.createNode(null) { path, config, mock, ts ->
object : MockNetwork.MockNode(path, config, mock, ts) {
override fun start(): MockNetwork.MockNode {
super.start()
(storage.attachments as NodeAttachmentService).checkAttachmentsOnLoad = false
return this
val n0 = network.createNode(null, nodeFactory = object : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, timestamperAddr: LegallyIdentifiableNode?): MockNetwork.MockNode {
return object : MockNetwork.MockNode(dir, config, network, timestamperAddr) {
override fun start(): MockNetwork.MockNode {
super.start()
(storage.attachments as NodeAttachmentService).checkAttachmentsOnLoad = false
return this
}
}
}
}
val n1 = network.createNode(n0.legallyIdentifableAddress)
})
val n1 = network.createNode(n0.legallyIdentifiableAddress)
// Insert an attachment into node zero's store directly.
val id = n0.storage.attachments.importAttachment(ByteArrayInputStream(fakeAttachment()))

View File

@ -12,6 +12,7 @@ import contracts.Cash
import contracts.CommercialPaper
import core.*
import core.crypto.SecureHash
import core.node.NodeConfiguration
import core.node.services.*
import core.testing.InMemoryMessagingNetwork
import core.testing.MockNetwork
@ -65,7 +66,7 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
transactionGroupFor<ContractState> {
val (aliceNode, bobNode) = net.createTwoNodes()
(bobNode.wallet as NodeWalletService).fillWithSomeTestCash(2000.DOLLARS)
val alicesFakePaper = fillUpForSeller(false, aliceNode.legallyIdentifableAddress.identity, null).second
val alicesFakePaper = fillUpForSeller(false, aliceNode.legallyIdentifiableAddress.identity, null).second
insertFakeTransactions(alicesFakePaper, aliceNode.services, aliceNode.storage.myLegalIdentityKey)
@ -73,7 +74,7 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
val aliceResult = TwoPartyTradeProtocol.runSeller(
aliceNode.smm,
aliceNode.legallyIdentifableAddress,
aliceNode.legallyIdentifiableAddress,
bobNode.net.myAddress,
lookup("alice's paper"),
1000.DOLLARS,
@ -82,7 +83,7 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
)
val bobResult = TwoPartyTradeProtocol.runBuyer(
bobNode.smm,
aliceNode.legallyIdentifableAddress,
aliceNode.legallyIdentifiableAddress,
aliceNode.net.myAddress,
1000.DOLLARS,
CommercialPaper.State::class.java,
@ -104,7 +105,7 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
var (aliceNode, bobNode) = net.createTwoNodes()
val aliceAddr = aliceNode.net.myAddress
val bobAddr = bobNode.net.myAddress as InMemoryMessagingNetwork.Handle
val timestamperAddr = aliceNode.legallyIdentifableAddress
val timestamperAddr = aliceNode.legallyIdentifiableAddress
(bobNode.wallet as NodeWalletService).fillWithSomeTestCash(2000.DOLLARS)
val alicesFakePaper = fillUpForSeller(false, timestamperAddr.identity, null).second
@ -163,16 +164,18 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
// ... bring the node back up ... the act of constructing the SMM will re-register the message handlers
// that Bob was waiting on before the reboot occurred.
bobNode = net.createNode(timestamperAddr, bobAddr.id) { path, nodeConfiguration, net, timestamper ->
object : MockNetwork.MockNode(path, nodeConfiguration, net, timestamper, bobAddr.id) {
override fun initialiseStorageService(dir: Path): StorageService {
val ss = super.initialiseStorageService(dir)
val smMap = ss.stateMachines
smMap.putAll(savedCheckpoints)
return ss
bobNode = net.createNode(timestamperAddr, bobAddr.id, object : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, timestamperAddr: LegallyIdentifiableNode?): MockNetwork.MockNode {
return object : MockNetwork.MockNode(dir, config, net, timestamperAddr, bobAddr.id) {
override fun initialiseStorageService(dir: Path): StorageService {
val ss = super.initialiseStorageService(dir)
val smMap = ss.stateMachines
smMap.putAll(savedCheckpoints)
return ss
}
}
}
}
})
// Find the future representing the result of this state machine again.
var bobFuture = bobNode.smm.findStateMachines(TwoPartyTradeProtocol.Buyer::class.java).single().second
@ -192,22 +195,24 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
// of gets and puts.
private fun makeNodeWithTracking(name: String): MockNetwork.MockNode {
// Create a node in the mock network ...
return net.createNode(null) { path, config, net, tsNode ->
object : MockNetwork.MockNode(path, config, net, tsNode) {
// That constructs the storage service object in a customised way ...
override fun constructStorageService(attachments: NodeAttachmentService, keypair: KeyPair, identity: Party): StorageServiceImpl {
// To use RecordingMaps instead of ordinary HashMaps.
return StorageServiceImpl(attachments, keypair, identity, { tableName -> name })
return net.createNode(null, nodeFactory = object : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, timestamperAddr: LegallyIdentifiableNode?): MockNetwork.MockNode {
return object : MockNetwork.MockNode(dir, config, network, timestamperAddr) {
// That constructs the storage service object in a customised way ...
override fun constructStorageService(attachments: NodeAttachmentService, keypair: KeyPair, identity: Party): StorageServiceImpl {
// To use RecordingMaps instead of ordinary HashMaps.
return StorageServiceImpl(attachments, keypair, identity, { tableName -> name })
}
}
}
}
})
}
@Test
fun checkDependenciesOfSaleAssetAreResolved() {
transactionGroupFor<ContractState> {
val aliceNode = makeNodeWithTracking("alice")
val timestamperAddr = aliceNode.legallyIdentifableAddress
val timestamperAddr = aliceNode.legallyIdentifiableAddress
val bobNode = makeNodeWithTracking("bob")
// Insert a prospectus type attachment into the commercial paper transaction.
@ -318,7 +323,7 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
var (aliceNode, bobNode) = net.createTwoNodes()
val aliceAddr = aliceNode.net.myAddress
val bobAddr = bobNode.net.myAddress as InMemoryMessagingNetwork.Handle
val timestamperAddr = aliceNode.legallyIdentifableAddress
val timestamperAddr = aliceNode.legallyIdentifiableAddress
val bobKey = bobNode.keyManagement.freshKey()
val bobsBadCash = fillUpForBuyer(bobError, bobKey.public).second

View File

@ -12,9 +12,7 @@ import co.paralleluniverse.fibers.Suspendable
import core.*
import core.crypto.SecureHash
import core.messaging.*
import core.node.services.NodeTimestamperService
import core.node.services.ServiceHub
import core.node.services.TimestampingError
import core.node.services.*
import core.protocols.ProtocolLogic
import core.serialization.serialize
import core.testing.InMemoryMessagingNetwork

View File

@ -9,12 +9,11 @@
package core.node.services
import contracts.Cash
import core.*
import core.testing.MockNetwork
import core.DOLLARS
import core.Fix
import core.TransactionBuilder
import core.bd
import core.testing.MockNetwork
import core.testutils.*
import core.utilities.BriefLogFormatter
import org.junit.Test
@ -86,7 +85,7 @@ class NodeInterestRatesTest {
val tx = TransactionBuilder()
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val protocol = RatesFixProtocol(tx, n2.legallyIdentifableAddress, fixOf, "0.675".bd, "0.1".bd)
val protocol = RatesFixProtocol(tx, n2.legallyIdentifiableAddress, fixOf, "0.675".bd, "0.1".bd)
BriefLogFormatter.initVerbose("rates")
val future = n1.smm.add("rates", protocol)

View File

@ -38,6 +38,8 @@ object TestUtils {
val keypair = generateKeyPair()
val keypair2 = generateKeyPair()
val keypair3 = generateKeyPair()
val keypair4 = generateKeyPair()
val keypair5 = generateKeyPair()
}
// A dummy time at which we will be pretending test transactions are created.
val TEST_TX_TIME = Instant.parse("2015-04-17T12:00:00.00Z")
@ -49,6 +51,14 @@ val MEGA_CORP_PUBKEY = MEGA_CORP_KEY.public
val MINI_CORP_KEY = TestUtils.keypair2
val MINI_CORP_PUBKEY = MINI_CORP_KEY.public
// TODO remove once mock API is retired
val EXCALIBUR_BANK_KEY = TestUtils.keypair4
val EXCALIBUR_BANK_PUBKEY = EXCALIBUR_BANK_KEY.public
// TODO remove once mock API is retired
val A_N_OTHER_BANK_KEY = TestUtils.keypair5
val A_N_OTHER_BANK_PUBKEY = A_N_OTHER_BANK_KEY.public
val ORACLE_KEY = TestUtils.keypair3
val ORACLE_PUBKEY = ORACLE_KEY.public
@ -64,11 +74,17 @@ val BOB = BOB_KEY.public
val MEGA_CORP = Party("MegaCorp", MEGA_CORP_PUBKEY)
val MINI_CORP = Party("MiniCorp", MINI_CORP_PUBKEY)
val ALL_TEST_KEYS = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, DummyTimestampingAuthority.key)
// TODO remove once mock API is retired
val EXCALIBUR_BANK = Party("Excalibur", EXCALIBUR_BANK_PUBKEY)
val A_N_OTHER_BANK = Party("ANOther",A_N_OTHER_BANK_PUBKEY)
val ALL_TEST_KEYS = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, EXCALIBUR_BANK_KEY, A_N_OTHER_BANK_KEY, DummyTimestampingAuthority.key)
val TEST_KEYS_TO_CORP_MAP: Map<PublicKey, Party> = mapOf(
MEGA_CORP_PUBKEY to MEGA_CORP,
MINI_CORP_PUBKEY to MINI_CORP,
EXCALIBUR_BANK_PUBKEY to EXCALIBUR_BANK,
A_N_OTHER_BANK_PUBKEY to A_N_OTHER_BANK,
DUMMY_TIMESTAMPER.identity.owningKey to DUMMY_TIMESTAMPER.identity
)