mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Merge branch 'master' into dynamic-loading
This commit is contained in:
commit
88a7406ec9
4
.idea/runConfigurations/All_tests.xml
generated
4
.idea/runConfigurations/All_tests.xml
generated
@ -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 />
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
33
src/main/kotlin/api/ResponseFilter.kt
Normal file
33
src/main/kotlin/api/ResponseFilter.kt
Normal 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")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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"))))
|
||||
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
}
|
@ -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()
|
||||
|
||||
|
106
src/main/kotlin/core/node/services/NetworkMapService.kt
Normal file
106
src/main/kotlin/core/node/services/NetworkMapService.kt
Normal 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()]
|
||||
}
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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 }
|
||||
}
|
34
src/main/kotlin/demos/DemoClock.kt
Normal file
34
src/main/kotlin/demos/DemoClock.kt
Normal 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
|
||||
}
|
||||
|
||||
}
|
@ -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() }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
756
src/main/resources/core/node/services/cities.txt
Normal file
756
src/main/resources/core/node/services/cities.txt
Normal 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
|
@ -1,2 +1,3 @@
|
||||
myLegalName = "Vast Global MegaCorp, Ltd"
|
||||
exportJMXto = "http"
|
||||
exportJMXto = "http"
|
||||
nearestCity = "The Moon"
|
@ -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("-----------")
|
||||
|
@ -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
|
||||
|
@ -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()))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user