├── .gitignore ├── LICENSE.adoc ├── README.adoc ├── _config.yml ├── docs ├── README.adoc └── images │ ├── X.png │ ├── XCL-Banner.png │ ├── XCL-Chain.png │ └── XCL-Title.png ├── examples ├── appreciation │ ├── bench.sh │ ├── pom.xml │ ├── run.sh │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── town │ │ │ │ │ └── lost │ │ │ │ │ └── examples │ │ │ │ │ └── appreciation │ │ │ │ │ ├── VanillaAppreciationGateway.java │ │ │ │ │ ├── VanillaAppreciationTransactions.java │ │ │ │ │ ├── api │ │ │ │ │ ├── AppreciationGateway.java │ │ │ │ │ ├── AppreciationMessages.java │ │ │ │ │ ├── AppreciationRequests.java │ │ │ │ │ ├── AppreciationResponses.java │ │ │ │ │ └── AppreciationTransactions.java │ │ │ │ │ ├── benchmark │ │ │ │ │ ├── Client.java │ │ │ │ │ ├── MutedTCPConnection.java │ │ │ │ │ ├── Node.java │ │ │ │ │ ├── Peer.java │ │ │ │ │ ├── Server.java │ │ │ │ │ ├── Traffic.java │ │ │ │ │ └── webapp │ │ │ │ │ │ ├── Benchmark.java │ │ │ │ │ │ └── ChronicleDecentredAppreciationDemoUI.java │ │ │ │ │ ├── decomposed │ │ │ │ │ ├── BlockEngineStarter.java │ │ │ │ │ ├── BruteForce.java │ │ │ │ │ ├── DecomposedUtil.java │ │ │ │ │ ├── GatewayStarter.java │ │ │ │ │ ├── Traffic.java │ │ │ │ │ └── VanillaAppreciationNode.java │ │ │ │ │ ├── dto │ │ │ │ │ ├── Give.java │ │ │ │ │ ├── OnBalance.java │ │ │ │ │ ├── OpeningBalance.java │ │ │ │ │ ├── QueryBalance.java │ │ │ │ │ └── Topup.java │ │ │ │ │ └── util │ │ │ │ │ ├── BalanceStore.java │ │ │ │ │ ├── Balances.java │ │ │ │ │ └── VanillaBalanceStore.java │ │ │ └── webapp │ │ │ │ ├── VAADIN │ │ │ │ └── themes │ │ │ │ │ └── mytheme │ │ │ │ │ ├── addons.scss │ │ │ │ │ ├── favicon.ico │ │ │ │ │ ├── mytheme.scss │ │ │ │ │ ├── styles.css │ │ │ │ │ └── styles.scss │ │ │ │ └── WEB-INF │ │ │ │ └── images │ │ │ │ └── cs_logo.png │ │ └── test │ │ │ ├── java │ │ │ └── town │ │ │ │ └── lost │ │ │ │ └── examples │ │ │ │ └── appreciation │ │ │ │ ├── AppreciationTester.java │ │ │ │ ├── EndToEndConversationTest.java │ │ │ │ ├── GiveTest.java │ │ │ │ ├── SingleMessageRoundtripTest.java │ │ │ │ ├── TestUtils.java │ │ │ │ ├── ThreePeersConnectionTest.java │ │ │ │ └── TopupTest.java │ │ │ └── resources │ │ │ ├── give │ │ │ └── one │ │ │ │ ├── in.yaml │ │ │ │ ├── out.yaml │ │ │ │ └── setup.yaml │ │ │ └── topup │ │ │ └── one │ │ │ ├── in.yaml │ │ │ ├── out.yaml │ │ │ └── setup.yaml │ ├── start_peer.sh │ ├── start_peer_graal.sh │ └── start_traffic.sh ├── exchange │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── town │ │ │ └── lost │ │ │ └── examples │ │ │ └── exchange │ │ │ ├── AccountBalance.java │ │ │ ├── ExchangeGateway.java │ │ │ ├── ExchangeMarket.java │ │ │ ├── ExchangeTransactionProcessor.java │ │ │ ├── api │ │ │ ├── ExchangeOut.java │ │ │ ├── ExchangeRequests.java │ │ │ └── ExchangeResponses.java │ │ │ ├── dto │ │ │ ├── CancelOrderEvent.java │ │ │ ├── CancelOrderRequest.java │ │ │ ├── Currency.java │ │ │ ├── CurrencyPair.java │ │ │ ├── DtoAliases.java │ │ │ ├── ExchangeCloseRequest.java │ │ │ ├── ExchangeConfig.java │ │ │ ├── MarketConfiguration.java │ │ │ ├── NewOrderRequest.java │ │ │ ├── OpeningBalanceEvent.java │ │ │ ├── Order.java │ │ │ ├── OrderCloseReason.java │ │ │ ├── Side.java │ │ │ ├── TradeClosedEvent.java │ │ │ ├── TradeEvent.java │ │ │ └── Validable.java │ │ │ └── util │ │ │ ├── CouldBeNaN.java │ │ │ └── Validators.java │ │ └── test │ │ ├── java │ │ └── town │ │ │ └── lost │ │ │ └── examples │ │ │ └── exchange │ │ │ ├── ExchangeMarketTest.java │ │ │ ├── ExchangeTester.java │ │ │ ├── MethodCall.java │ │ │ ├── TestUtils.java │ │ │ └── dto │ │ │ ├── CancelOrderEventTest.java │ │ │ ├── CancelOrderRequestTest.java │ │ │ ├── NewOrderRequestTest.java │ │ │ ├── OpeningBalanceEventTest.java │ │ │ └── TradeEventTest.java │ │ └── resources │ │ └── orders │ │ └── simpleMatch │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml └── pom.xml ├── pom.xml ├── rfc ├── Chain-Evolution.adoc └── Decentred-Address.adoc ├── src ├── main │ └── java │ │ └── net │ │ └── openhft │ │ └── chronicle │ │ └── decentred │ │ ├── api │ │ ├── AddressManagementRequests.java │ │ ├── AddressManagementResponses.java │ │ ├── BlockEvents.java │ │ ├── BlockchainPhase.java │ │ ├── ChainLifecycleRequests.java │ │ ├── ConnectionStatusListener.java │ │ ├── MessageListener.java │ │ ├── MessageRouter.java │ │ ├── MessageToListener.java │ │ ├── SystemMessageListener.java │ │ ├── SystemMessages.java │ │ ├── TransactionProcessor.java │ │ └── Verifier.java │ │ ├── dto │ │ ├── VerificationEvent.java │ │ ├── address │ │ │ ├── CreateAddressEvent.java │ │ │ ├── CreateAddressRequest.java │ │ │ └── InvalidationEvent.java │ │ ├── base │ │ │ ├── DtoAliases.java │ │ │ ├── EmptyTransientFieldHandler.java │ │ │ ├── SelfSignedMessage.java │ │ │ ├── SignedMessage.java │ │ │ ├── TransientFieldHandler.java │ │ │ ├── VanillaSignedMessage.java │ │ │ └── trait │ │ │ │ ├── HasAddressToBlockNumberMap.java │ │ │ │ ├── HasBlockNumber.java │ │ │ │ ├── HasChainAddress.java │ │ │ │ ├── HasDtoParser.java │ │ │ │ ├── HasTransientFieldHandler.java │ │ │ │ └── HasWeekNumber.java │ │ ├── blockevent │ │ │ ├── AddressToBlockNumberUtil.java │ │ │ ├── EndOfRoundBlockEvent.java │ │ │ ├── TransactionBlockEvent.java │ │ │ ├── TransactionBlockGossipEvent.java │ │ │ └── TransactionBlockVoteEvent.java │ │ ├── chainlifecycle │ │ │ ├── AssignDelegatesRequest.java │ │ │ ├── CreateChainRequest.java │ │ │ └── CreateTokenRequest.java │ │ └── error │ │ │ └── ApplicationErrorResponse.java │ │ ├── internal │ │ ├── server │ │ │ ├── LastGossipVoter.java │ │ │ ├── MultiMessageToListener.java │ │ │ ├── QueuingChainer.java │ │ │ ├── SingleMessageToListener.java │ │ │ ├── VanillaBlockEngine.java │ │ │ ├── VanillaChainer.java │ │ │ ├── VanillaTransactionProcessor.java │ │ │ └── VanillaVoteTaker.java │ │ ├── unmodifiable │ │ │ ├── ThrowUtil.java │ │ │ ├── UnmodifiableLongCursor.java │ │ │ ├── UnmodifiableLongLongMap.java │ │ │ └── UnmodifiableLongSet.java │ │ └── util │ │ │ └── ShortUtil.java │ │ ├── remote │ │ ├── net │ │ │ ├── AbstractTCPConnection.java │ │ │ ├── TCPClientListener.java │ │ │ ├── TCPConnection.java │ │ │ ├── TCPServer.java │ │ │ ├── TCPServerConnectionListener.java │ │ │ ├── VanillaTCPClient.java │ │ │ ├── VanillaTCPServer.java │ │ │ └── VanillaTCPServerConnection.java │ │ └── rpc │ │ │ ├── RPCClient.java │ │ │ └── RPCServer.java │ │ ├── server │ │ ├── BlockEngine.java │ │ ├── BlockReplayer.java │ │ ├── Chainer.java │ │ ├── DecentredServer.java │ │ ├── Gateway.java │ │ ├── GatewayConfiguration.java │ │ ├── Gossiper.java │ │ ├── RPCBuilder.java │ │ ├── RunningMessageToListener.java │ │ ├── VanillaBlockReplayer.java │ │ ├── VanillaGateway.java │ │ ├── VanillaGossiper.java │ │ ├── VanillaVerifyIP.java │ │ ├── VoteTaker.java │ │ ├── Voter.java │ │ └── trait │ │ │ └── HasTcpMessageListener.java │ │ └── util │ │ ├── AddressLongConverter.java │ │ ├── DecentredUtil.java │ │ ├── DtoParselet.java │ │ ├── DtoParser.java │ │ ├── DtoRegistry.java │ │ ├── HasSuperInterface.java │ │ ├── IntObjMap.java │ │ ├── KeyPair.java │ │ ├── LetterBase32.java │ │ ├── LongDoubleMap.java │ │ ├── LongLongMap.java │ │ ├── LongObjMap.java │ │ ├── LongU32Writer.java │ │ ├── OffsetIntConverter.java │ │ ├── PublicKeyRegistry.java │ │ ├── SmallIntObjMap.java │ │ ├── VanillaDtoParser.java │ │ ├── VanillaDtoRegistry.java │ │ └── VanillaPublicKeyRegistry.java └── test │ ├── java │ └── net │ │ └── openhft │ │ └── chronicle │ │ └── decentred │ │ ├── SystemMessagesTest.java │ │ ├── dto │ │ ├── ApplicationErrorResponseTest.java │ │ ├── CreateAddressRequestTest.java │ │ ├── EndOfRoundBlockEventTest.java │ │ ├── EndOfRoundBlockEventTester.java │ │ ├── TransactionBlockEventTest.java │ │ ├── TransactionBlockGossipEventTest.java │ │ ├── VerificationEventTest.java │ │ └── fundamental │ │ │ ├── address │ │ │ ├── CreateAddressEventFundamentalTest.java │ │ │ ├── CreateAddressRequestFundamentalTest.java │ │ │ └── InvalidationEventFundamentalTest.java │ │ │ ├── base │ │ │ └── AbstractFundamentalDtoTest.java │ │ │ ├── chainevent │ │ │ ├── EndOfRoundBlockEventFundamentalTest.java │ │ │ ├── TransactionBlockEventFundamentalTest.java │ │ │ ├── TransactionBlockGossipEventFundamentalTest.java │ │ │ └── TransactionBlockVoteEventFundamentalTest.java │ │ │ ├── chainlifecycle │ │ │ ├── AssignDelegatesRequestFundamentalTest.java │ │ │ ├── CreateChainRequestFundamentalTest.java │ │ │ └── CreateTokenRequestFundamentalTest.java │ │ │ └── error │ │ │ └── ApplicationErrorResponseFundamentalTest.java │ │ ├── internal │ │ ├── unmodifiable │ │ │ └── UnmodifiableLongLongMapTest.java │ │ └── util │ │ │ └── ShortUtilTest.java │ │ ├── remote │ │ ├── net │ │ │ ├── EchoClientMain.java │ │ │ └── EchoServerMain.java │ │ └── rpc │ │ │ └── RPCTest.java │ │ ├── server │ │ ├── DecentredClientServerTest.java │ │ ├── GatewayTester.java │ │ ├── RPCGatewayTest.java │ │ ├── TransactionProcessorTester.java │ │ ├── VanillaGatewayTest.java │ │ └── VanillaTransactionProcessorTest.java │ │ ├── util │ │ ├── AddressLongConverterTest.java │ │ ├── DecentredUtilTest.java │ │ └── KeyPairTest.java │ │ └── verification │ │ ├── VerifyIPTest.java │ │ └── VerifyIPTester.java │ └── resources │ ├── gateway │ ├── createAddressRequest │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ ├── endOfRoundBlockEvent │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ ├── invalidationEvent │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ ├── transactionBlockEvent │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ ├── transactionBlockGossipEvent │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ ├── transactionBlockVoteEvent │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ └── verificationEvent │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ ├── genesis │ ├── one │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ └── sample │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ ├── raw │ └── endOfRoundBlockEvent │ │ ├── in.yaml │ │ ├── out.yaml │ │ └── setup.yaml │ └── verification │ ├── one │ ├── in.yaml │ ├── out.yaml │ └── setup.yaml │ └── step1 │ ├── in.yaml │ ├── out.yaml │ └── setup.yaml └── system.properties /.gitignore: -------------------------------------------------------------------------------- 1 | ### How to update 2 | # This is copied from OpenHFT/.gitignore 3 | # update the original and run OpenHFT/update_gitignore.sh 4 | 5 | ### Compiled class file 6 | *.class 7 | 8 | ### Package Files 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | ### Log file 14 | *.log 15 | 16 | ### IntelliJ 17 | *.iml 18 | *.ipr 19 | *.iws 20 | .idea 21 | compat_reports 22 | .attach_pid* 23 | 24 | ### Virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | 27 | ### Maven template 28 | target/ 29 | pom.xml.tag 30 | pom.xml.releaseBackup 31 | pom.xml.versionsBackup 32 | pom.xml.next 33 | release.properties 34 | 35 | ### Eclipse template 36 | *.pydevproject 37 | .metadata 38 | .gradle 39 | bin/ 40 | tmp/ 41 | *.tmp 42 | *.bak 43 | *.swp 44 | *~.nib 45 | local.properties 46 | .classpath 47 | .project 48 | .settings/ 49 | .loadpath 50 | 51 | ### Queue files 52 | *.cq4t 53 | *.cq4 54 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /docs/README.adoc: -------------------------------------------------------------------------------- 1 | = Documentation 2 | Peter Lawrey 3 | 4 | == Getting Started 5 | 6 | == Performance Testing -------------------------------------------------------------------------------- /docs/images/X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/docs/images/X.png -------------------------------------------------------------------------------- /docs/images/XCL-Banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/docs/images/XCL-Banner.png -------------------------------------------------------------------------------- /docs/images/XCL-Chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/docs/images/XCL-Chain.png -------------------------------------------------------------------------------- /docs/images/XCL-Title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/docs/images/XCL-Title.png -------------------------------------------------------------------------------- /examples/appreciation/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CLASS=${1} 4 | shift 5 | PARAMS="$@" 6 | echo "Starting ${CLASS} with params ${PARAMS}" 7 | 8 | mvn -q exec:java -Dexec.mainClass="town.lost.examples.appreciation.benchmark.${CLASS}" -Dexec.args="${PARAMS}" 2>&1 | tee /tmp/run.$$.log 9 | 10 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/VanillaAppreciationTransactions.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageRouter; 4 | import town.lost.examples.appreciation.api.AppreciationResponses; 5 | import town.lost.examples.appreciation.api.AppreciationTransactions; 6 | import town.lost.examples.appreciation.dto.Give; 7 | import town.lost.examples.appreciation.dto.OnBalance; 8 | import town.lost.examples.appreciation.dto.OpeningBalance; 9 | import town.lost.examples.appreciation.dto.Topup; 10 | import town.lost.examples.appreciation.util.BalanceStore; 11 | import town.lost.examples.appreciation.util.Balances; 12 | 13 | /** 14 | * Run from the blockchain. 15 | */ 16 | public class VanillaAppreciationTransactions implements AppreciationTransactions { 17 | protected MessageRouter router; 18 | private final BalanceStore balanceStore; 19 | private final OnBalance onBalance = new OnBalance(); 20 | 21 | public VanillaAppreciationTransactions( 22 | MessageRouter router, 23 | BalanceStore balanceStore) { 24 | this.router = router; 25 | this.balanceStore = balanceStore; 26 | } 27 | 28 | @Override 29 | public void openingBalance(OpeningBalance openingBalance) { 30 | balanceStore.setBalance(openingBalance.balanceAddress(), openingBalance.amount()); 31 | } 32 | 33 | @Override 34 | public void give(Give give) { 35 | long fromKey = give.address(); 36 | long toKey = give.toAddress(); 37 | if (balanceStore.subtractBalance(fromKey, give.amount())) { 38 | balanceStore.addBalance(toKey, give.amount()); 39 | 40 | onBalance.reset(); 41 | onBalance.timestampUS(give.timestampUS()); 42 | router.to(fromKey) 43 | .onBalance(onBalance.init(fromKey, balanceStore.getBalances(fromKey))); 44 | 45 | onBalance.reset(); 46 | onBalance.timestampUS(give.timestampUS()); 47 | router.to(toKey) 48 | .onBalance(onBalance.init(toKey, balanceStore.getBalances(toKey))); 49 | } 50 | } 51 | 52 | @Override 53 | public void topup(Topup topup) { 54 | balanceStore.setFreeBalance(topup.amount()); 55 | onBalance.timestampUS(topup.timestampUS()); 56 | long address = topup.address(); 57 | Balances balances = balanceStore.getBalances(address); 58 | if (balances != null) 59 | router.to(address) 60 | .onBalance(onBalance.init(address, balances)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/api/AppreciationGateway.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.api; 2 | 3 | import net.openhft.chronicle.decentred.api.ConnectionStatusListener; 4 | 5 | /** 6 | * Gateway processor which handles queries from the client 7 | * as well as validate and pass transactions 8 | */ 9 | public interface AppreciationGateway extends 10 | AppreciationRequests, 11 | ConnectionStatusListener { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/api/AppreciationMessages.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.api; 2 | 3 | public interface AppreciationMessages extends AppreciationRequests, AppreciationResponses {} -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/api/AppreciationRequests.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.decentred.api.AddressManagementRequests; 5 | import town.lost.examples.appreciation.dto.QueryBalance; 6 | 7 | /** 8 | * Transactions passed through the block chainevent 9 | */ 10 | public interface AppreciationRequests extends 11 | AddressManagementRequests, 12 | AppreciationTransactions { 13 | 14 | /** 15 | * Report the current balance for this public key. 16 | */ 17 | @MethodId(0x0020) 18 | void queryBalance(QueryBalance queryBalance); 19 | } 20 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/api/AppreciationResponses.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.decentred.api.SystemMessageListener; 5 | import town.lost.examples.appreciation.dto.OnBalance; 6 | 7 | public interface AppreciationResponses extends SystemMessageListener { 8 | @MethodId(0x3000) 9 | void onBalance(OnBalance onBalance); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/api/AppreciationTransactions.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import town.lost.examples.appreciation.dto.Give; 5 | import town.lost.examples.appreciation.dto.OpeningBalance; 6 | import town.lost.examples.appreciation.dto.Topup; 7 | 8 | /** 9 | * Transactions passed through the block chainevent 10 | */ 11 | public interface AppreciationTransactions { 12 | 13 | /** 14 | * Report the current balance for this public key. 15 | */ 16 | @MethodId(0x0001) 17 | void openingBalance(OpeningBalance openingBalance); 18 | 19 | @MethodId(0x0010) 20 | void give(Give give); 21 | 22 | @MethodId(0x0020) 23 | void topup(Topup topup); 24 | } 25 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/benchmark/MutedTCPConnection.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.benchmark; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.decentred.remote.net.TCPConnection; 5 | 6 | import java.io.IOException; 7 | import java.nio.ByteBuffer; 8 | 9 | public final class MutedTCPConnection implements TCPConnection { 10 | 11 | private static final TCPConnection INSTANCE = new MutedTCPConnection(); 12 | 13 | private MutedTCPConnection() {} 14 | 15 | @Override 16 | public void write(BytesStore bytes) throws IOException {} 17 | 18 | @Override 19 | public void write(ByteBuffer buffer) throws IOException {} 20 | 21 | @Override 22 | public void close() {} 23 | 24 | public static TCPConnection get() { 25 | return INSTANCE; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/benchmark/Node.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.benchmark; 2 | 3 | import net.openhft.chronicle.decentred.server.RPCBuilder; 4 | import net.openhft.chronicle.decentred.util.DecentredUtil; 5 | import net.openhft.chronicle.decentred.util.KeyPair; 6 | 7 | import static java.util.Objects.requireNonNull; 8 | 9 | public abstract class Node { 10 | private final KeyPair keyPair; 11 | private final RPCBuilder rpcBuilder; 12 | 13 | public Node(long seed, Class uClass, Class tClass) { 14 | requireNonNull(uClass); 15 | requireNonNull(tClass); 16 | 17 | keyPair = new KeyPair(seed); 18 | 19 | rpcBuilder = RPCBuilder.of(17, uClass, tClass) 20 | //.addClusterAddress(address) // Todo: Why do we add our own address? 21 | .keyPair(keyPair); 22 | 23 | } 24 | 25 | public static long addressFromSeed(int seed) { // TODO - convenient for bootstrapping seeded keys 26 | KeyPair kp = new KeyPair(seed); 27 | return DecentredUtil.toAddress(kp.publicKey); 28 | } 29 | 30 | public void addClusterAddress(long address) { 31 | rpcBuilder.addClusterAddress(address); 32 | } 33 | 34 | public long address() { 35 | return keyPair.address(); 36 | } 37 | 38 | public KeyPair getKeyPair() { 39 | return keyPair; 40 | } 41 | 42 | public RPCBuilder getRpcBuilder() { 43 | return rpcBuilder; 44 | } 45 | 46 | protected abstract void close(); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/decomposed/DecomposedUtil.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.decomposed; 2 | 3 | public enum DecomposedUtil { 4 | ; // none 5 | 6 | public static final String REGION = "ENGCMD"; // England, London, Camden 7 | 8 | } 9 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/decomposed/VanillaAppreciationNode.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.decomposed; 2 | 3 | import net.openhft.chronicle.decentred.remote.rpc.RPCServer; 4 | import town.lost.examples.appreciation.api.AppreciationMessages; 5 | import town.lost.examples.appreciation.api.AppreciationRequests; 6 | import town.lost.examples.appreciation.benchmark.Node; 7 | 8 | public abstract class VanillaAppreciationNode extends Node { 9 | 10 | private final RPCServer rpcServer; 11 | 12 | protected VanillaAppreciationNode(long seed) { 13 | super(seed, AppreciationMessages.class, AppreciationRequests.class); 14 | rpcServer = createRpcServer(); 15 | } 16 | 17 | protected abstract RPCServer createRpcServer(); 18 | 19 | @Override 20 | protected void close() { 21 | rpcServer.close(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/dto/Give.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.dto; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.bytes.BytesOut; 5 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 6 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 7 | import net.openhft.chronicle.wire.LongConversion; 8 | 9 | public class Give extends VanillaSignedMessage { 10 | @LongConversion(AddressLongConverter.class) 11 | private long toAddress; 12 | 13 | private double amount; 14 | 15 | public Give() { 16 | } 17 | 18 | public Give(long toAddress, double amount) { 19 | init(toAddress, amount); 20 | } 21 | 22 | public Give init(long toAddress, double amount) { 23 | this.toAddress = toAddress; 24 | this.amount = amount; 25 | return this; 26 | } 27 | 28 | public long toAddress() { 29 | return toAddress; 30 | } 31 | 32 | public Give toAddress(long toAddress) { 33 | this.toAddress = toAddress; 34 | return this; 35 | } 36 | 37 | public double amount() { 38 | return amount; 39 | } 40 | 41 | public Give amount(double amount) { 42 | this.amount = amount; 43 | return this; 44 | } 45 | 46 | @Override 47 | protected void readMarshallableInternal(Bytes bytes) { 48 | timestampUS = bytes.readLong(); 49 | address = bytes.readLong(); 50 | toAddress = bytes.readLong(); 51 | amount = bytes.readDouble(); 52 | } 53 | 54 | @Override 55 | protected void writeMarshallableInternal(BytesOut bytes) { 56 | bytes.writeLong(timestampUS); 57 | bytes.writeLong(address); 58 | bytes.writeLong(toAddress); 59 | bytes.writeDouble(amount); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/dto/OnBalance.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | import town.lost.examples.appreciation.util.Balances; 7 | 8 | public class OnBalance extends VanillaSignedMessage { 9 | @LongConversion(AddressLongConverter.class) 10 | private long balanceAddress; 11 | private double amount; 12 | private double freeAmount; 13 | 14 | public OnBalance() { 15 | } 16 | 17 | public OnBalance init(long balanceAddress, Balances balances) { 18 | this.balanceAddress = balanceAddress; 19 | this.amount = balances.balance(); 20 | this.freeAmount = balances.freeBalance(); 21 | return this; 22 | } 23 | 24 | public long balanceAddress() { 25 | return balanceAddress; 26 | } 27 | 28 | public OnBalance balanceAddress(long balanceAddress) { 29 | this.balanceAddress = balanceAddress; 30 | return this; 31 | } 32 | 33 | public double amount() { 34 | return amount; 35 | } 36 | 37 | public OnBalance amount(double amount) { 38 | this.amount = amount; 39 | return this; 40 | } 41 | 42 | public double freeAmount() { 43 | return freeAmount; 44 | } 45 | 46 | public OnBalance freeAmount(double freeAmount) { 47 | this.freeAmount = freeAmount; 48 | return this; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/dto/OpeningBalance.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | 7 | public class OpeningBalance extends VanillaSignedMessage { 8 | @LongConversion(AddressLongConverter.class) 9 | private long balanceAddress; 10 | 11 | private double amount; 12 | 13 | public OpeningBalance() { 14 | } 15 | 16 | public OpeningBalance(long balanceAddress, double amount) { 17 | init(balanceAddress, amount); 18 | } 19 | 20 | public OpeningBalance init(long balanceAddress, double amount) { 21 | this.balanceAddress = balanceAddress; 22 | this.amount = amount; 23 | return this; 24 | } 25 | 26 | public long balanceAddress() { 27 | return balanceAddress; 28 | } 29 | 30 | public OpeningBalance balanceAddress(long balanceAddress) { 31 | this.balanceAddress = balanceAddress; 32 | return this; 33 | } 34 | 35 | public double amount() { 36 | return amount; 37 | } 38 | 39 | public OpeningBalance amount(double amount) { 40 | this.amount = amount; 41 | return this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/dto/QueryBalance.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | 5 | public class QueryBalance extends VanillaSignedMessage { 6 | // no additional fields 7 | } 8 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/dto/Topup.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.dto; 2 | 3 | import net.openhft.chronicle.core.annotation.UsedViaReflection; 4 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 5 | 6 | /** 7 | * Automated version of Give that is used to allocate new balances for distribution on a regular basis. 8 | */ 9 | public class Topup extends VanillaSignedMessage { 10 | private double amount; 11 | 12 | @UsedViaReflection 13 | public Topup() { 14 | } 15 | 16 | public double amount() { 17 | return amount; 18 | } 19 | 20 | public Topup amount(double amount) { 21 | this.amount = amount; 22 | return this; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/util/BalanceStore.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.util; 2 | 3 | public interface BalanceStore { 4 | Balances getBalances(long address); 5 | 6 | boolean subtractBalance(long address, double amount); 7 | 8 | void addBalance(long address, double amount); 9 | 10 | void setBalance(long address, double amount); 11 | 12 | void setFreeBalance(double amount); 13 | } 14 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/util/Balances.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.util; 2 | 3 | import net.openhft.chronicle.wire.AbstractBytesMarshallable; 4 | 5 | public class Balances extends AbstractBytesMarshallable { 6 | double balance, freeBalance; 7 | 8 | public double balance() { 9 | return balance; 10 | } 11 | 12 | public double freeBalance() { 13 | return freeBalance; 14 | } 15 | 16 | public double total() { 17 | return balance + freeBalance; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/java/town/lost/examples/appreciation/util/VanillaBalanceStore.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation.util; 2 | 3 | import net.openhft.chronicle.decentred.util.DecentredUtil; 4 | import net.openhft.chronicle.decentred.util.LongObjMap; 5 | 6 | import java.util.StringJoiner; 7 | 8 | public class VanillaBalanceStore implements BalanceStore { 9 | private final LongObjMap amountsMap = LongObjMap.withExpectedSize(Balances.class, 1024); 10 | 11 | @Override 12 | public Balances getBalances(long address) { 13 | synchronized (amountsMap) { 14 | return amountsMap.get(address); 15 | } 16 | } 17 | 18 | @Override 19 | public boolean subtractBalance(long address, double amount) { 20 | assert amount >= 0; 21 | synchronized (amountsMap) { 22 | Balances balances = amountsMap.get(address); 23 | if (balances == null) 24 | return false; 25 | if (balances.total() < amount) 26 | return false; 27 | double free2 = Math.min(balances.freeBalance, amount); 28 | balances.freeBalance -= free2; 29 | amount -= free2; 30 | 31 | double balance = Math.min(balances.balance, amount); 32 | balances.balance -= balance; 33 | return true; 34 | } 35 | } 36 | 37 | @Override 38 | public void addBalance(long address, double amount) { 39 | assert amount >= 0; 40 | synchronized (amountsMap) { 41 | Balances balances = amountsMap.get(address); 42 | if (balances == null) { 43 | amountsMap.justPut(address, balances); 44 | } 45 | balances.balance += amount; 46 | } 47 | } 48 | 49 | @Override 50 | public void setBalance(long address, double amount) { 51 | assert amount >= 0; 52 | synchronized (amountsMap) { 53 | Balances balances = amountsMap.get(address); 54 | if (balances == null) { 55 | amountsMap.justPut(address, balances = new Balances()); 56 | } 57 | balances.balance = amount; 58 | } 59 | } 60 | 61 | @Override 62 | public void setFreeBalance(double amount) { 63 | synchronized (amountsMap) { 64 | amountsMap.forEach((k, b) -> b.freeBalance = amount); 65 | } 66 | } 67 | 68 | public String toString() { 69 | final StringJoiner builder = new StringJoiner(", ", "{", "}"); 70 | amountsMap.forEach((address, balance) -> { 71 | builder.add(DecentredUtil.toAddressString(address) + " has " + balance.balance()); 72 | }); 73 | return builder.toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/webapp/VAADIN/themes/mytheme/addons.scss: -------------------------------------------------------------------------------- 1 | /* This file is automatically managed and will be overwritten from time to time. */ 2 | /* Do not manually edit this file. */ 3 | 4 | /* Import and include this mixin into your project theme to include the addon themes */ 5 | @mixin addons { 6 | } 7 | 8 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/webapp/VAADIN/themes/mytheme/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/examples/appreciation/src/main/webapp/VAADIN/themes/mytheme/favicon.ico -------------------------------------------------------------------------------- /examples/appreciation/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss: -------------------------------------------------------------------------------- 1 | // If you edit this file you need to compile the theme. See README.md for details. 2 | 3 | // Global variable overrides. Must be declared before importing Valo. 4 | 5 | // Defines the plaintext font size, weight and family. Font size affects general component sizing. 6 | //$v-font-size: 16px; 7 | //$v-font-weight: 300; 8 | //$v-font-family: "Open Sans", sans-serif; 9 | 10 | // Defines the border used by all components. 11 | //$v-border: 1px solid (v-shade 0.7); 12 | //$v-border-radius: 4px; 13 | 14 | // Affects the color of some component elements, e.g Button, Panel title, etc 15 | //$v-background-color: hsl(210, 0%, 98%); 16 | // Affects the color of content areas, e.g Panel and Window content, TextField input etc 17 | //$v-app-background-color: $v-background-color; 18 | 19 | // Affects the visual appearance of all components 20 | //$v-gradient: v-linear 8%; 21 | //$v-bevel-depth: 30%; 22 | //$v-shadow-opacity: 5%; 23 | 24 | // Defines colors for indicating status (focus, success, failure) 25 | //$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically 26 | //$v-friendly-color: #2c9720; 27 | //$v-error-indicator-color: #ed473b; 28 | 29 | // For more information, see: https://vaadin.com/book/-/page/themes.valo.html 30 | // Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples 31 | 32 | @import "../valo/valo.scss"; 33 | 34 | @mixin mytheme { 35 | @include valo; 36 | 37 | // Insert your own theme rules here 38 | } 39 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/webapp/VAADIN/themes/mytheme/styles.scss: -------------------------------------------------------------------------------- 1 | @import "mytheme.scss"; 2 | @import "addons.scss"; 3 | 4 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes. 5 | // The actual styles should be defined in mytheme.scss 6 | 7 | .mytheme { 8 | @include addons; 9 | @include mytheme; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /examples/appreciation/src/main/webapp/WEB-INF/images/cs_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/examples/appreciation/src/main/webapp/WEB-INF/images/cs_logo.png -------------------------------------------------------------------------------- /examples/appreciation/src/test/java/town/lost/examples/appreciation/AppreciationTester.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageRouter; 4 | import town.lost.examples.appreciation.api.AppreciationRequests; 5 | import town.lost.examples.appreciation.api.AppreciationResponses; 6 | 7 | /** 8 | * Combining interface for all messages 9 | */ 10 | interface AppreciationTester extends 11 | MessageRouter, 12 | 13 | AppreciationResponses, 14 | AppreciationRequests { 15 | } 16 | -------------------------------------------------------------------------------- /examples/appreciation/src/test/java/town/lost/examples/appreciation/GiveTest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.core.time.UniqueMicroTimeProvider; 5 | import net.openhft.chronicle.decentred.dto.address.CreateAddressRequest; 6 | import net.openhft.chronicle.decentred.util.DecentredUtil; 7 | import net.openhft.chronicle.decentred.util.KeyPair; 8 | import net.openhft.chronicle.wire.TextWire; 9 | import org.junit.jupiter.api.Test; 10 | import town.lost.examples.appreciation.dto.Give; 11 | import town.lost.examples.appreciation.dto.OpeningBalance; 12 | 13 | import static town.lost.examples.appreciation.TestUtils.test; 14 | 15 | final class GiveTest { 16 | public static void main(String[] args) { 17 | KeyPair kp7 = new KeyPair(7); 18 | 19 | KeyPair kp17 = new KeyPair(17); 20 | 21 | TextWire wire = new TextWire(Bytes.elasticHeapByteBuffer(128)); 22 | AppreciationTester tester = wire.methodWriter(AppreciationTester.class); 23 | tester.createAddressRequest(new CreateAddressRequest() 24 | .address(0) 25 | .timestampUS(UniqueMicroTimeProvider.INSTANCE.currentTimeMicros()) 26 | .publicKey(kp7.publicKey)); 27 | tester.createAddressRequest(new CreateAddressRequest() 28 | .address(0) 29 | .timestampUS(UniqueMicroTimeProvider.INSTANCE.currentTimeMicros()) 30 | .publicKey(kp17.publicKey)); 31 | 32 | long address1 = DecentredUtil.toAddress(kp7.publicKey); 33 | long address2 = DecentredUtil.toAddress(kp17.publicKey); 34 | tester.openingBalance(new OpeningBalance() 35 | .timestampUS(UniqueMicroTimeProvider.INSTANCE.currentTimeMicros()) 36 | .init(address1, 100)); 37 | tester.openingBalance(new OpeningBalance() 38 | .timestampUS(UniqueMicroTimeProvider.INSTANCE.currentTimeMicros()) 39 | .init(address2, 20)); 40 | 41 | tester.give(new Give() 42 | .timestampUS(UniqueMicroTimeProvider.INSTANCE.currentTimeMicros()) 43 | .address(address1) 44 | .init(address2, 0.0)); 45 | 46 | System.out.println(wire); 47 | } 48 | 49 | @Test 50 | void testGiveOne() { 51 | test("give/one"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/appreciation/src/test/java/town/lost/examples/appreciation/TestUtils.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation; 2 | 3 | import net.openhft.chronicle.core.io.IORuntimeException; 4 | import net.openhft.chronicle.wire.TextMethodTester; 5 | import town.lost.examples.appreciation.util.VanillaBalanceStore; 6 | 7 | import java.io.IOException; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | public enum TestUtils { 12 | ; // none 13 | 14 | public static void test(String basename) { 15 | TextMethodTester tester = new TextMethodTester<>( 16 | basename + "/in.yaml", 17 | TestUtils::createGateway, 18 | AppreciationTester.class, 19 | basename + "/out.yaml"); 20 | tester.setup(basename + "/setup.yaml"); 21 | try { 22 | tester.run(); 23 | } catch (IOException e) { 24 | throw new IORuntimeException(e); 25 | } 26 | assertEquals(tester.expected(), tester.actual()); 27 | } 28 | 29 | public static VanillaAppreciationGateway createGateway(AppreciationTester tester) { 30 | VanillaBalanceStore balanceStore = new VanillaBalanceStore(); 31 | VanillaAppreciationTransactions blockchain = new VanillaAppreciationTransactions(tester, balanceStore); 32 | return new VanillaAppreciationGateway(0, null, null, tester, blockchain, balanceStore); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/appreciation/src/test/java/town/lost/examples/appreciation/TopupTest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.appreciation; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | final class TopupTest { 6 | 7 | @Test 8 | void testTopup(){ 9 | TestUtils.test("topup/one"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/appreciation/src/test/resources/give/one/in.yaml: -------------------------------------------------------------------------------- 1 | give: { 2 | timestampUS: 2018-08-20T11:31:15.379010, 3 | address: nphccofmpy6ci, 4 | toAddress: ud6jbceicts2, 5 | amount: 30.0 6 | } 7 | --- -------------------------------------------------------------------------------- /examples/appreciation/src/test/resources/give/one/out.yaml: -------------------------------------------------------------------------------- 1 | to: nphccofmpy6ci 2 | onBalance: { 3 | timestampUS: 2018-08-20T11:31:15.37901, 4 | address: ., 5 | balanceAddress: nphccofmpy6ci, 6 | amount: 80.0, 7 | freeAmount: 0.0 8 | } 9 | to: ud6jbceicts2 10 | onBalance: { 11 | timestampUS: 2018-08-20T11:31:15.37901, 12 | address: ., 13 | balanceAddress: ud6jbceicts2, 14 | amount: 50.0, 15 | freeAmount: 10.0 16 | } 17 | --- -------------------------------------------------------------------------------- /examples/appreciation/src/test/resources/give/one/setup.yaml: -------------------------------------------------------------------------------- 1 | createAccountRequest: { 2 | timestampUS: 2018-08-20T11:31:15.319, 3 | address: ., 4 | publicKey: !!binary 9M9t8hyt2kEJmL46Fs+si0VigLTMQt9OafgMm3ljIOg= 5 | } 6 | --- 7 | createAccountRequest: { 8 | timestampUS: 2018-08-20T11:31:15.373, 9 | address: ., 10 | publicKey: !!binary TsXED8x8VoxtLgRu7iPaz4aAhfQUtmvee9KRyhDKk+o= 11 | } 12 | --- 13 | openingBalance: { 14 | timestampUS: 2018-08-20T11:31:15.373001, 15 | address: ., 16 | balanceAddress: nphccofmpy6ci, 17 | amount: 100.0 18 | } 19 | --- 20 | openingBalance: { 21 | timestampUS: 2018-08-20T11:31:15.379, 22 | address: ., 23 | balanceAddress: ud6jbceicts2, 24 | amount: 20.0 25 | } 26 | --- 27 | topup: { 28 | timestampUS: 2018-08-20T11:31:15.379010, 29 | address: nphccofmpy6ci, 30 | amount: 10.0, 31 | } 32 | --- 33 | -------------------------------------------------------------------------------- /examples/appreciation/src/test/resources/topup/one/in.yaml: -------------------------------------------------------------------------------- 1 | # this adds money to an account. 2 | topup: { 3 | timestampUS: 2018-08-20T11:31:15.379010, 4 | address: nphccofmpy6ci, 5 | amount: 20.0, 6 | } 7 | --- -------------------------------------------------------------------------------- /examples/appreciation/src/test/resources/topup/one/out.yaml: -------------------------------------------------------------------------------- 1 | to: nphccofmpy6ci 2 | onBalance: { 3 | timestampUS: 2018-08-20T11:31:15.37901, 4 | address: ., 5 | balanceAddress: nphccofmpy6ci, 6 | amount: 100.0, 7 | freeAmount: 20.0 8 | } 9 | --- -------------------------------------------------------------------------------- /examples/appreciation/src/test/resources/topup/one/setup.yaml: -------------------------------------------------------------------------------- 1 | createAccountRequest: { 2 | timestampUS: 2018-08-20T11:31:15.319, 3 | address: ., 4 | publicKey: !!binary 9M9t8hyt2kEJmL46Fs+si0VigLTMQt9OafgMm3ljIOg= 5 | } 6 | --- 7 | createAccountRequest: { 8 | timestampUS: 2018-08-20T11:31:15.373, 9 | address: ., 10 | publicKey: !!binary TsXED8x8VoxtLgRu7iPaz4aAhfQUtmvee9KRyhDKk+o= 11 | } 12 | --- 13 | openingBalance: { 14 | timestampUS: 2018-08-20T11:31:15.373001, 15 | address: ., 16 | balanceAddress: nphccofmpy6ci, 17 | amount: 100.0 18 | } 19 | --- 20 | openingBalance: { 21 | timestampUS: 2018-08-20T11:31:15.379, 22 | address: ., 23 | balanceAddress: ud6jbceicts2, 24 | amount: 20.0 25 | } 26 | --- 27 | -------------------------------------------------------------------------------- /examples/appreciation/start_peer.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [ $# -eq 0 ]; then 3 | echo "Usage: $0 peer# [0..2]" 4 | exit 1 5 | fi 6 | echo "Starting peer# $1" 7 | if [ ! -d target ] ; then 8 | mvn install 9 | fi 10 | mvn -q exec:java -Dexec.mainClass="town.lost.examples.appreciation.benchmark.Peer" -Dexec.args="$1 0.0.0.0:10000,0.0.0.0:10001,0.0.0.0:10002" 11 | -------------------------------------------------------------------------------- /examples/appreciation/start_peer_graal.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [ $# -eq 0 ]; then 3 | echo "Usage: $0 peer# [0..2]" 4 | exit 1 5 | fi 6 | echo "Starting peer# $1" 7 | JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.0/Contents/Home M2_HOME=/Applications/apache-maven-3.6.0 /Applications/apache-maven-3.6.0/bin/mvn -q exec:java -Dexec.mainClass="town.lost.examples.appreciation.benchmark.Peer" -Dexec.args="$1 0.0.0.0:10000,0.0.0.0:10001,0.0.0.0:10002" 8 | -------------------------------------------------------------------------------- /examples/appreciation/start_traffic.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Starting Traffic" 3 | if [ ! -d target ] ; then 4 | mvn install 5 | fi 6 | mvn -q exec:java -Dexec.mainClass="town.lost.examples.appreciation.benchmark.Traffic" -Dexec.args="0.0.0.0:10000 $1" 7 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/AccountBalance.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange; 2 | 3 | import town.lost.examples.exchange.dto.Currency; 4 | import town.lost.examples.exchange.dto.OpeningBalanceEvent; 5 | 6 | import java.util.EnumMap; 7 | import java.util.Map; 8 | 9 | public class AccountBalance { 10 | 11 | private final EnumMap currencyMap = new EnumMap<>(Currency.class); 12 | 13 | public AccountBalance(OpeningBalanceEvent openingBalanceEvent) { 14 | for (Map.Entry entry : openingBalanceEvent.balances().entrySet()) { 15 | currencyMap.put(entry.getKey(), new CurrencyBalance().available(entry.getValue())); 16 | } 17 | } 18 | 19 | static class CurrencyBalance { 20 | double available; 21 | double reserved; 22 | 23 | public double available() { 24 | return available; 25 | } 26 | 27 | public CurrencyBalance available(double available) { 28 | this.available = available; 29 | return this; 30 | } 31 | 32 | public double reserved() { 33 | return reserved; 34 | } 35 | 36 | public CurrencyBalance reserved(double reserved) { 37 | this.reserved = reserved; 38 | return this; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/ExchangeGateway.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageRouter; 4 | import net.openhft.chronicle.decentred.dto.error.ApplicationErrorResponse; 5 | import town.lost.examples.exchange.api.ExchangeRequests; 6 | import town.lost.examples.exchange.api.ExchangeResponses; 7 | import town.lost.examples.exchange.dto.*; 8 | 9 | public class ExchangeGateway implements ExchangeRequests { 10 | private final MessageRouter router; 11 | private final ExchangeRequests blockchain; 12 | 13 | public ExchangeGateway(MessageRouter router, ExchangeRequests blockchain) { 14 | this.router = router; 15 | this.blockchain = blockchain; 16 | } 17 | 18 | protected boolean privilegedAddress(long address) { 19 | return true; 20 | } 21 | 22 | @Override 23 | public void exchangeConfig(ExchangeConfig exchangeConfig) { 24 | if (!privilegedAddress(exchangeConfig.address())) { 25 | router.to(0).applicationError(new ApplicationErrorResponse().init(exchangeConfig, "Not authorized")); 26 | return; 27 | } 28 | blockchain.exchangeConfig(exchangeConfig); 29 | } 30 | 31 | @Override 32 | public void openningBalanceEvent(OpeningBalanceEvent openingBalanceEvent) { 33 | if (!privilegedAddress(openingBalanceEvent.address())) { 34 | router.to(0).applicationError(new ApplicationErrorResponse().init(openingBalanceEvent, "Not authorized")); 35 | return; 36 | } 37 | openingBalanceEvent.validate(); 38 | blockchain.openningBalanceEvent(openingBalanceEvent); 39 | } 40 | 41 | @Override 42 | public void newOrderRequest(NewOrderRequest newOrderRequest) { 43 | newOrderRequest.validate(); 44 | blockchain.newOrderRequest(newOrderRequest); 45 | } 46 | 47 | @Override 48 | public void cancelOrderCommand(CancelOrderRequest cancelOrderRequest) { 49 | cancelOrderRequest.validate(); 50 | blockchain.cancelOrderCommand(cancelOrderRequest); 51 | } 52 | 53 | @Override 54 | public void exchangeCloseRequest(ExchangeCloseRequest exchangeCloseRequest) { 55 | if (!privilegedAddress(exchangeCloseRequest.address())) { 56 | router.to(0).applicationError(new ApplicationErrorResponse().init(exchangeCloseRequest, "Not authorized")); 57 | return; 58 | } 59 | blockchain.exchangeCloseRequest(exchangeCloseRequest); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/api/ExchangeOut.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.api; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageRouter; 4 | import net.openhft.chronicle.decentred.api.SystemMessageListener; 5 | 6 | public interface ExchangeOut extends SystemMessageListener, MessageRouter { 7 | } 8 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/api/ExchangeRequests.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import town.lost.examples.exchange.dto.*; 5 | 6 | public interface ExchangeRequests { 7 | @MethodId(0x0010) 8 | void exchangeConfig(ExchangeConfig exchangeConfig); 9 | 10 | @MethodId(0x0011) 11 | void exchangeCloseRequest(ExchangeCloseRequest exchangeCloseRequest); 12 | 13 | @MethodId(0x0020) 14 | void openningBalanceEvent(OpeningBalanceEvent openingBalanceEvent); 15 | 16 | @MethodId(0x0100) 17 | void newOrderRequest(NewOrderRequest newOrderRequest); 18 | 19 | @MethodId(0x0101) 20 | void cancelOrderCommand(CancelOrderRequest cancelOrderRequest); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/api/ExchangeResponses.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.decentred.dto.error.ApplicationErrorResponse; 5 | import town.lost.examples.exchange.dto.TradeClosedEvent; 6 | import town.lost.examples.exchange.dto.TradeEvent; 7 | 8 | public interface ExchangeResponses { 9 | @MethodId(0x0200) 10 | void tradeEvent(TradeEvent tradeEvent); 11 | 12 | @MethodId(0x0201) 13 | void tradeClosedEvent(TradeClosedEvent tradeClosedEvent); 14 | 15 | /** 16 | * Notify an application error occurred in response to a message passed. 17 | * 18 | * @param applicationErrorResponse occurred 19 | */ 20 | @MethodId(0xFF10) 21 | void applicationError(ApplicationErrorResponse applicationErrorResponse); 22 | } 23 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/CancelOrderEvent.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | import net.openhft.chronicle.wire.MicroTimestampLongConverter; 7 | 8 | public class CancelOrderEvent extends VanillaSignedMessage { 9 | @LongConversion(MicroTimestampLongConverter.class) 10 | private long orderTimestampUS; 11 | @LongConversion(AddressLongConverter.class) 12 | private long orderAddress; 13 | 14 | public CancelOrderEvent() { 15 | } 16 | 17 | public CancelOrderEvent(long orderTimestampUS, long orderAddress) { 18 | this.orderTimestampUS = orderTimestampUS; 19 | this.orderAddress = orderAddress; 20 | } 21 | 22 | public long orderTimestampUS() { 23 | return orderTimestampUS; 24 | } 25 | 26 | public CancelOrderEvent orderTimestampUS(long orderTimestampUS) { 27 | this.orderTimestampUS = orderTimestampUS; 28 | return this; 29 | } 30 | 31 | public long orderAddress() { 32 | return orderAddress; 33 | } 34 | 35 | public CancelOrderEvent orderAddress(long orderAddress) { 36 | this.orderAddress = orderAddress; 37 | return this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/CancelOrderRequest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.wire.LongConversion; 5 | import net.openhft.chronicle.wire.MicroTimestampLongConverter; 6 | 7 | public class CancelOrderRequest extends VanillaSignedMessage implements Validable { 8 | 9 | private CurrencyPair currencyPair; 10 | @LongConversion(MicroTimestampLongConverter.class) 11 | private long orderTimestampUS; 12 | 13 | public CancelOrderRequest() { 14 | 15 | } 16 | 17 | public long orderTimestampUS() { 18 | return orderTimestampUS; 19 | } 20 | 21 | public CancelOrderRequest orderTimestampUS(long orderTimestampUS) { 22 | this.orderTimestampUS = orderTimestampUS; 23 | return this; 24 | } 25 | 26 | public CurrencyPair currencyPair() { 27 | return currencyPair; 28 | } 29 | 30 | public CancelOrderRequest currencyPair(CurrencyPair currencyPair) { 31 | this.currencyPair = currencyPair; 32 | return this; 33 | } 34 | 35 | public void validate() { 36 | if (currencyPair == null) throw new IllegalStateException(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/Currency.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | public enum Currency { 4 | XCL, 5 | USD, 6 | EUR, 7 | GBP, 8 | CHF, 9 | KRW 10 | } 11 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/CurrencyPair.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | public enum CurrencyPair { 4 | USDXCL(Currency.USD, Currency.XCL), 5 | EURXCL(Currency.EUR, Currency.XCL), 6 | GBPXCL(Currency.GBP, Currency.XCL), 7 | CHFXCL(Currency.CHF, Currency.XCL), 8 | KRWXCL(Currency.KRW, Currency.XCL); 9 | 10 | private final Currency ccy1; 11 | private final Currency ccy2; 12 | 13 | CurrencyPair(Currency ccy1, Currency ccy2) { 14 | this.ccy1 = ccy1; 15 | this.ccy2 = ccy2; 16 | } 17 | 18 | public Currency ccy1() { 19 | return ccy1; 20 | } 21 | 22 | public Currency ccy2() { 23 | return ccy2; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/DtoAliases.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.core.pool.ClassAliasPool; 4 | 5 | public enum DtoAliases { 6 | ; // none 7 | 8 | static { 9 | ClassAliasPool.CLASS_ALIASES.addAlias( 10 | CancelOrderEvent.class, 11 | CancelOrderRequest.class, 12 | NewOrderRequest.class, 13 | OpeningBalanceEvent.class, 14 | TradeEvent.class 15 | ); 16 | } 17 | 18 | public static void addAliases() { 19 | net.openhft.chronicle.decentred.dto.base.DtoAliases.addAliases(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/ExchangeCloseRequest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | 5 | public class ExchangeCloseRequest extends VanillaSignedMessage { 6 | String reason; 7 | 8 | public String reason() { 9 | return reason; 10 | } 11 | 12 | public ExchangeCloseRequest reason(String reason) { 13 | this.reason = reason; 14 | return this; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/ExchangeConfig.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.wire.AbstractBytesMarshallable; 5 | 6 | import java.util.LinkedHashMap; 7 | import java.util.Map; 8 | 9 | public class ExchangeConfig extends VanillaSignedMessage { 10 | private Map currencies = new LinkedHashMap<>(); 11 | 12 | public Map currencies() { 13 | return currencies; 14 | } 15 | 16 | public static class CurrencyConfig extends AbstractBytesMarshallable { 17 | private double tickSize; 18 | 19 | public double tickSize() { 20 | return tickSize; 21 | } 22 | 23 | public CurrencyConfig tickSize(double tickSize) { 24 | this.tickSize = tickSize; 25 | return this; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/MarketConfiguration.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | public class MarketConfiguration { 4 | } 5 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/NewOrderRequest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | 5 | public class NewOrderRequest extends VanillaSignedMessage implements Validable { 6 | 7 | private Side side; 8 | private double quantity; 9 | private double maxPrice; 10 | private CurrencyPair currencyPair; 11 | private long ttlMillis; 12 | 13 | public NewOrderRequest() { 14 | 15 | } 16 | 17 | public NewOrderRequest(long sourceAddress, long eventTime, Side side, double qty, double maxPrice, CurrencyPair currencyPair, long ttlMillis) { 18 | this.address(sourceAddress); 19 | this.timestampUS(eventTime); 20 | this.side = side; 21 | this.quantity = qty; 22 | this.maxPrice = maxPrice; 23 | this.currencyPair = currencyPair; 24 | this.ttlMillis = ttlMillis; 25 | } 26 | 27 | public NewOrderRequest(double quantity, double maxPrice, CurrencyPair currencyPair, long ttlMillis, Side side) { 28 | this.quantity = quantity; 29 | this.maxPrice = maxPrice; 30 | this.currencyPair = currencyPair; 31 | this.ttlMillis = ttlMillis; 32 | this.side = side; 33 | } 34 | 35 | public double quantity() { 36 | return quantity; 37 | } 38 | 39 | public NewOrderRequest quantity(double quantity) { 40 | this.quantity = quantity; 41 | return this; 42 | } 43 | 44 | public double maxPrice() { 45 | return maxPrice; 46 | } 47 | 48 | public NewOrderRequest maxPrice(double maxPrice) { 49 | this.maxPrice = maxPrice; 50 | return this; 51 | } 52 | 53 | public CurrencyPair currencyPair() { 54 | return currencyPair; 55 | } 56 | 57 | public NewOrderRequest currencyPair(CurrencyPair currencyPair) { 58 | this.currencyPair = currencyPair; 59 | return this; 60 | } 61 | 62 | public long ttlMillis() { 63 | return ttlMillis; 64 | } 65 | 66 | public NewOrderRequest ttlMillis(long ttlMillis) { 67 | this.ttlMillis = ttlMillis; 68 | return this; 69 | } 70 | 71 | public Side side() { 72 | return side; 73 | } 74 | 75 | public NewOrderRequest side(Side action) { 76 | this.side = action; 77 | return this; 78 | } 79 | 80 | @Override 81 | public void validate() throws IllegalStateException { 82 | if (side == null || currencyPair == null) throw new IllegalStateException(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/OpeningBalanceEvent.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | 7 | import java.util.EnumMap; 8 | import java.util.Map; 9 | 10 | public class OpeningBalanceEvent extends VanillaSignedMessage implements Validable { 11 | @LongConversion(AddressLongConverter.class) 12 | private long balanceAddress; 13 | private final Map balances = new EnumMap<>(Currency.class); 14 | 15 | public Map balances() { 16 | return balances; 17 | } 18 | 19 | public long balanceAddress() { 20 | return balanceAddress; 21 | } 22 | 23 | public OpeningBalanceEvent balanceAddress(long balanceAccount) { 24 | this.balanceAddress = balanceAccount; 25 | return this; 26 | } 27 | 28 | @Override 29 | public void validate() throws IllegalStateException { 30 | for (Double value : balances.values()) { 31 | if (value == null || !(value >= 0)) 32 | throw new IllegalStateException(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/Order.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.wire.AbstractMarshallable; 4 | 5 | import java.util.Comparator; 6 | 7 | public class Order extends AbstractMarshallable { 8 | 9 | private final long ownerAddress; 10 | private final long ownerOrderTime; 11 | private final long orderId; 12 | private final long expires; // millis 13 | private final double quantity; 14 | private final double price; 15 | private final Side side; 16 | private long filled = 0; 17 | 18 | public Order(long orderId, Side side, double quantity, double price, long expires, long ownerAddress, long ownerOrderTime) { 19 | this.orderId = orderId; 20 | this.side = side; 21 | this.quantity = quantity; 22 | this.price = price; 23 | this.expires = expires; 24 | this.ownerAddress = ownerAddress; 25 | this.ownerOrderTime = ownerOrderTime; 26 | } 27 | 28 | public static Comparator getBuyComparator() { 29 | return Comparator.comparingDouble(o -> -o.price) 30 | .thenComparingDouble(o -> o.orderId); 31 | } 32 | 33 | public static Comparator getSellComparator() { 34 | return Comparator.comparingDouble(o -> +o.price) 35 | .thenComparingDouble(o -> o.orderId); 36 | } 37 | 38 | public double quantityLeft() { 39 | return quantity - filled; 40 | } 41 | 42 | public long expirationTime() { 43 | return expires; 44 | } 45 | 46 | public double price() { 47 | return price; 48 | } 49 | 50 | public long ownerAddress() { 51 | return ownerAddress; 52 | } 53 | 54 | public long ownerOrderTime() { 55 | return ownerOrderTime; 56 | } 57 | 58 | public boolean matches(long address, long orderTime) { 59 | return (ownerAddress == address) && (ownerOrderTime == orderTime); 60 | } 61 | 62 | public Side side() { 63 | return side; 64 | } 65 | 66 | public double getQuantity() { 67 | return quantity; 68 | } 69 | 70 | public double fill(double fillQty) { 71 | assert fillQty <= quantityLeft(); 72 | filled += fillQty; 73 | return quantityLeft(); 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | return Long.hashCode(orderId); 79 | } 80 | 81 | @Override 82 | public boolean equals(Object obj) { 83 | assert obj instanceof Order; 84 | return (this == obj) || (orderId == ((Order) obj).orderId); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/OrderCloseReason.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | public enum OrderCloseReason { 4 | USER_REQUEST(0), 5 | UNKNOWN_SYMBOL(1), 6 | EXCHANGE_CLOSED(2), 7 | TIME_OUT(3); 8 | 9 | private final byte value; 10 | 11 | OrderCloseReason(int value) { 12 | this.value = (byte) value; 13 | } 14 | 15 | public byte value() { 16 | return value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/Side.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import town.lost.examples.exchange.util.CouldBeNaN; 5 | 6 | import static java.lang.Math.nextUp; 7 | 8 | public enum Side { 9 | BUY { 10 | @Override 11 | public @NotNull 12 | int compare(double newPrice, double referencePrice, double precision) { 13 | if (newPrice > referencePrice + precision) 14 | return +1; 15 | if (referencePrice > newPrice + precision) 16 | return -1; 17 | return 0; 18 | } 19 | 20 | @Override 21 | public @CouldBeNaN 22 | double roundWorse(@CouldBeNaN double value, @CouldBeNaN double tickSize) { 23 | return tickSize * Math.floor(value / tickSize); 24 | } 25 | 26 | @Override 27 | public Side other() { 28 | return SELL; 29 | } 30 | }, 31 | SELL { 32 | @Override 33 | public int compare(double newPrice, double referencePrice, double precision) { 34 | return BUY.compare(referencePrice, newPrice, precision); 35 | } 36 | 37 | @Override 38 | public @CouldBeNaN 39 | double roundWorse(@CouldBeNaN double value, @CouldBeNaN double tickSize) { 40 | return tickSize * Math.ceil(value / tickSize); 41 | } 42 | 43 | @Override 44 | public Side other() { 45 | return BUY; 46 | } 47 | }; 48 | 49 | static final double DEFAULT_PRECISION_FACTOR = 1E-7; 50 | 51 | static { 52 | assert (BUY.ordinal() == 0) && (SELL.ordinal() == 1); 53 | } 54 | 55 | public static double getDefaultPrecision(double tickSize) { 56 | return nextUp(tickSize * DEFAULT_PRECISION_FACTOR); 57 | } 58 | 59 | @NotNull 60 | protected abstract int compare(double newPrice, double referencePrice, double precision); 61 | 62 | public boolean isBetterOrSame(double price, double referencePrice, double precision) { 63 | return compare(price, referencePrice, precision) >= 0; 64 | } 65 | 66 | public abstract double roundWorse(double value, double precision); 67 | 68 | public abstract Side other(); 69 | } 70 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/TradeClosedEvent.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | import net.openhft.chronicle.wire.MicroTimestampLongConverter; 7 | 8 | public class TradeClosedEvent extends VanillaSignedMessage { 9 | @LongConversion(MicroTimestampLongConverter.class) 10 | private long orderTimestampUS; 11 | @LongConversion(AddressLongConverter.class) 12 | private long orderAddress; 13 | private CurrencyPair currencyPair; 14 | private Side side; 15 | private OrderCloseReason orderCloseReason; 16 | 17 | public TradeClosedEvent(Order order) { 18 | orderAddress = order.ownerAddress(); 19 | orderTimestampUS = order.ownerOrderTime(); 20 | side = order.side(); 21 | } 22 | 23 | public long orderTimestampUS() { 24 | return orderTimestampUS; 25 | } 26 | 27 | public TradeClosedEvent orderTimestampUS(long orderTimestampUS) { 28 | this.orderTimestampUS = orderTimestampUS; 29 | return this; 30 | } 31 | 32 | public long orderAddress() { 33 | return orderAddress; 34 | } 35 | 36 | public TradeClosedEvent orderAddress(long orderAddress) { 37 | this.orderAddress = orderAddress; 38 | return this; 39 | } 40 | 41 | public CurrencyPair currencyPair() { 42 | return currencyPair; 43 | } 44 | 45 | public TradeClosedEvent currencyPair(CurrencyPair currencyPair) { 46 | this.currencyPair = currencyPair; 47 | return this; 48 | } 49 | 50 | public Side side() { 51 | return side; 52 | } 53 | 54 | public TradeClosedEvent side(Side side) { 55 | this.side = side; 56 | return this; 57 | } 58 | 59 | public OrderCloseReason orderCloseReason() { 60 | return orderCloseReason; 61 | } 62 | 63 | public TradeClosedEvent orderCloseReason(OrderCloseReason orderCloseReason) { 64 | this.orderCloseReason = orderCloseReason; 65 | return this; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/TradeEvent.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | import net.openhft.chronicle.wire.MicroTimestampLongConverter; 7 | 8 | public class TradeEvent extends VanillaSignedMessage { 9 | @LongConversion(MicroTimestampLongConverter.class) 10 | private long orderTimestampUS; 11 | @LongConversion(AddressLongConverter.class) 12 | private long orderAddress; 13 | private double quantity; 14 | private double price; 15 | private CurrencyPair currencyPair; 16 | private Side side; 17 | 18 | public TradeEvent() { 19 | } 20 | 21 | public TradeEvent(Order order) { 22 | orderAddress = order.ownerAddress(); 23 | orderTimestampUS = order.ownerOrderTime(); 24 | quantity = order.getQuantity(); 25 | price = order.price(); 26 | side = order.side(); 27 | } 28 | 29 | public long orderTimestampUS() { 30 | return orderTimestampUS; 31 | } 32 | 33 | public TradeEvent orderTimestampUS(long orderTimestampUS) { 34 | this.orderTimestampUS = orderTimestampUS; 35 | return this; 36 | } 37 | 38 | public long orderAddress() { 39 | return orderAddress; 40 | } 41 | 42 | public TradeEvent orderAddress(long orderAddress) { 43 | this.orderAddress = orderAddress; 44 | return this; 45 | } 46 | 47 | public double quantity() { 48 | return quantity; 49 | } 50 | 51 | public TradeEvent quantity(double quantity) { 52 | this.quantity = quantity; 53 | return this; 54 | } 55 | 56 | public double price() { 57 | return price; 58 | } 59 | 60 | public TradeEvent price(double price) { 61 | this.price = price; 62 | return this; 63 | } 64 | 65 | public CurrencyPair currencyPair() { 66 | return currencyPair; 67 | } 68 | 69 | public TradeEvent currencyPair(CurrencyPair currencyPair) { 70 | this.currencyPair = currencyPair; 71 | return this; 72 | } 73 | 74 | public Side action() { 75 | return side; 76 | } 77 | 78 | public TradeEvent action(Side action) { 79 | this.side = action; 80 | return this; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/dto/Validable.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | public interface Validable { 4 | void validate() throws IllegalStateException; 5 | } 6 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/util/CouldBeNaN.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.util; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Target(value = {ElementType.PARAMETER, ElementType.TYPE_USE}) 7 | @Retention(value = RetentionPolicy.RUNTIME) 8 | public @interface CouldBeNaN { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /examples/exchange/src/main/java/town/lost/examples/exchange/util/Validators.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.util; 2 | 3 | import static java.lang.Double.isInfinite; 4 | import static java.lang.Double.isNaN; 5 | 6 | public enum Validators { 7 | ; // none 8 | 9 | public static double notNaN(double value) { 10 | return notNaN(value, ""); 11 | } 12 | 13 | public static double notNaN(double value, String message) { 14 | if (isNaN(value)) 15 | throw new IllegalArgumentException(message); 16 | 17 | return value; 18 | } 19 | 20 | public static double notInfinite(double value) { 21 | if (isInfinite(value)) 22 | throw new IllegalArgumentException(); 23 | return value; 24 | } 25 | 26 | public static double validNumber(double value) { 27 | return notInfinite(notNaN(value)); 28 | } 29 | 30 | public static double positive(double value) { 31 | if (value >= 0) 32 | return value; 33 | throw new IllegalArgumentException(); 34 | } 35 | 36 | public static long positive(long value) { 37 | if (value >= 0) 38 | return value; 39 | throw new IllegalArgumentException(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/ExchangeTester.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange; 2 | 3 | import net.openhft.chronicle.decentred.dto.error.ApplicationErrorResponse; 4 | import town.lost.examples.exchange.api.ExchangeOut; 5 | import town.lost.examples.exchange.api.ExchangeRequests; 6 | import town.lost.examples.exchange.api.ExchangeResponses; 7 | 8 | interface ExchangeTester extends ExchangeRequests, ExchangeOut, ExchangeResponses { 9 | void setCurrentTime(long currentTimeMillis); 10 | 11 | @Override 12 | default void applicationError(ApplicationErrorResponse applicationErrorResponse) { 13 | ExchangeOut.super.applicationError(applicationErrorResponse); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/MethodCall.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange; 2 | 3 | import net.openhft.chronicle.wire.Marshallable; 4 | import net.openhft.chronicle.wire.Wires; 5 | 6 | public class MethodCall { 7 | private final String methodName; 8 | private final Object[] params; 9 | 10 | public MethodCall(String methodName, Object[] params) { 11 | super(); 12 | this.methodName = methodName; 13 | this.params = new Object[params.length]; 14 | for (int i = 0; i < params.length; i++) { 15 | if (params[i] instanceof Marshallable) { 16 | this.params[i] = Wires.deepCopy((Marshallable) params[i]); 17 | } else { 18 | this.params[i] = params[i]; 19 | } 20 | } 21 | } 22 | 23 | public String getMethodName() { 24 | return methodName; 25 | } 26 | 27 | public Object[] getParams() { 28 | return params; 29 | } 30 | 31 | @SuppressWarnings("unchecked") 32 | public T getParams(int index) { 33 | return (T) params[index]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/TestUtils.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange; 2 | 3 | import net.openhft.chronicle.core.annotation.UsedViaReflection; 4 | import net.openhft.chronicle.core.io.IORuntimeException; 5 | import net.openhft.chronicle.wire.TextMethodTester; 6 | 7 | import java.io.IOException; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | public enum TestUtils { ; 12 | 13 | public static void test(String basename) { 14 | TextMethodTester tester = new TextMethodTester<>( 15 | basename + "/in.yaml", 16 | TestUtils::createGateway, 17 | ExchangeTester.class, 18 | basename + "/out.yaml"); 19 | tester.setup(basename + "/setup.yaml"); 20 | try { 21 | tester.run(); 22 | } catch (IOException e) { 23 | throw new IORuntimeException(e); 24 | } 25 | assertEquals(tester.expected(), tester.actual()); 26 | } 27 | 28 | public static ExchangeGateway createGateway(ExchangeTester tester) { 29 | ExchangeTransactionProcessor blockchain = new ExchangeTransactionProcessor(tester); 30 | return new ExchangeGateway(tester, blockchain) { 31 | @Override 32 | protected boolean privilegedAddress(long address) { 33 | return address != 0; 34 | } 35 | 36 | @UsedViaReflection 37 | public void setCurrentTime(long currentTime) { 38 | blockchain.setCurrentTime(currentTime); 39 | } 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/dto/CancelOrderEventTest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.core.time.SetTimeProvider; 5 | import net.openhft.chronicle.decentred.util.DecentredUtil; 6 | import net.openhft.chronicle.decentred.util.KeyPair; 7 | import net.openhft.chronicle.wire.Marshallable; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | final class CancelOrderEventTest { 13 | static { 14 | DtoAliases.addAliases(); 15 | } 16 | @Test 17 | void marshallable() { 18 | KeyPair kp7 = new KeyPair(7); 19 | BytesStore publicKey1 = kp7.publicKey; 20 | BytesStore secretKey1 = kp7.secretKey; 21 | 22 | CancelOrderEvent cor = new CancelOrderEvent() 23 | .orderTimestampUS(new SetTimeProvider("2018-03-04T18:03:03.311111").currentTimeMicros()) 24 | .orderAddress(DecentredUtil.parseAddress("bye.now")) 25 | .protocol(1) 26 | .messageType(1004) 27 | .sign(secretKey1, new SetTimeProvider("2018-03-04T18:03:05.644532")); 28 | 29 | assertEquals("!CancelOrderEvent {\n" + 30 | " timestampUS: 2018-03-04T18:03:05.644532,\n" + 31 | " address: nphccofmpy6ci,\n" + 32 | " orderTimestampUS: 2018-03-04T18:03:03.311111,\n" + 33 | " orderAddress: bye.now\n" + 34 | "}\n", cor.toString()); 35 | CancelOrderEvent cor2 = Marshallable.fromString(cor.toString()); 36 | assertEquals(cor2, cor); 37 | } 38 | } -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/dto/CancelOrderRequestTest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.core.time.SetTimeProvider; 5 | import net.openhft.chronicle.decentred.util.KeyPair; 6 | import net.openhft.chronicle.wire.Marshallable; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | final class CancelOrderRequestTest { 12 | static { 13 | DtoAliases.addAliases(); 14 | } 15 | 16 | @Test 17 | void marshallable() { 18 | KeyPair kp7 = new KeyPair(7); 19 | BytesStore publicKey1 = kp7.publicKey; 20 | BytesStore secretKey1 = kp7.secretKey; 21 | CancelOrderRequest cor = new CancelOrderRequest() 22 | .orderTimestampUS(new SetTimeProvider("2018-03-04T18:03:05.364453").currentTimeMicros()) 23 | .protocol(1) 24 | .messageType(1002) 25 | .currencyPair(CurrencyPair.USDXCL) 26 | .sign(secretKey1, new SetTimeProvider("2018-03-04T18:03:05.644532")); 27 | 28 | assertEquals("!CancelOrderRequest {\n" + 29 | " timestampUS: 2018-03-04T18:03:05.644532,\n" + 30 | " address: nphccofmpy6ci,\n" + 31 | " currencyPair: USDXCL,\n" + 32 | " orderTimestampUS: 2018-03-04T18:03:05.364453\n" + 33 | "}\n", cor.toString()); 34 | CancelOrderRequest cor2 = Marshallable.fromString(cor.toString()); 35 | assertEquals(cor2, cor); 36 | } 37 | } -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/dto/NewOrderRequestTest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.core.time.SetTimeProvider; 5 | import net.openhft.chronicle.decentred.util.KeyPair; 6 | import net.openhft.chronicle.wire.Marshallable; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | final class NewOrderRequestTest { 12 | static { 13 | DtoAliases.addAliases(); 14 | } 15 | 16 | @Test 17 | void marshallable() { 18 | KeyPair kp7 = new KeyPair(7); 19 | BytesStore publicKey1 = kp7.publicKey; 20 | BytesStore secretKey1 = kp7.secretKey; 21 | 22 | NewOrderRequest nor = new NewOrderRequest() 23 | .side(Side.BUY) 24 | .currencyPair(CurrencyPair.EURXCL) 25 | .maxPrice(1000.0) 26 | .quantity(1000.0) 27 | .ttlMillis(300) 28 | .protocol(1) 29 | .messageType(1001) 30 | .sign(secretKey1, new SetTimeProvider("2018-03-04T18:03:05.364453")); 31 | assertEquals("!NewOrderRequest {\n" + 32 | " timestampUS: 2018-03-04T18:03:05.364453,\n" + 33 | " address: nphccofmpy6ci,\n" + 34 | " side: BUY,\n" + 35 | " quantity: 1E3,\n" + 36 | " maxPrice: 1E3,\n" + 37 | " currencyPair: EURXCL,\n" + 38 | " ttlMillis: 300\n" + 39 | "}\n", nor.toString()); 40 | NewOrderRequest nor2 = Marshallable.fromString(nor.toString()); 41 | assertEquals(nor2, nor); 42 | } 43 | } -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/dto/OpeningBalanceEventTest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.core.time.SetTimeProvider; 5 | import net.openhft.chronicle.decentred.util.DecentredUtil; 6 | import net.openhft.chronicle.decentred.util.KeyPair; 7 | import net.openhft.chronicle.wire.Marshallable; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | final class OpeningBalanceEventTest { 13 | static { 14 | DtoAliases.addAliases(); 15 | } 16 | 17 | @Test 18 | void balances() { 19 | KeyPair kp7 = new KeyPair(7); 20 | BytesStore publicKey1 = kp7.publicKey; 21 | BytesStore secretKey1 = kp7.secretKey; 22 | 23 | OpeningBalanceEvent obe = new OpeningBalanceEvent() 24 | .protocol(1).messageType(1) 25 | .balanceAddress(DecentredUtil.toAddress(publicKey1)); 26 | obe.balances().put(Currency.XCL, 128.0); 27 | obe.balances().put(Currency.USD, 10000.0); 28 | obe.balances().put(Currency.KRW, 11_000_000.0); 29 | obe.sign(secretKey1, new SetTimeProvider("2018-08-20T11:31:15.379010")); 30 | 31 | assertEquals("!OpeningBalanceEvent {\n" + 32 | " timestampUS: 2018-08-20T11:31:15.37901,\n" + 33 | " address: nphccofmpy6ci,\n" + 34 | " balanceAddress: nphccofmpy6ci,\n" + 35 | " balances: {\n" + 36 | " ? XCL: 128.0,\n" + 37 | " ? USD: 10E3,\n" + 38 | " ? KRW: 11E6\n" + 39 | " }\n" + 40 | "}\n", obe.toString()); 41 | 42 | OpeningBalanceEvent obe2 = Marshallable.fromString(obe.toString()); 43 | assertEquals(obe2, obe); 44 | } 45 | } -------------------------------------------------------------------------------- /examples/exchange/src/test/java/town/lost/examples/exchange/dto/TradeEventTest.java: -------------------------------------------------------------------------------- 1 | package town.lost.examples.exchange.dto; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.bytes.BytesStore; 5 | import net.openhft.chronicle.core.time.SetTimeProvider; 6 | import net.openhft.chronicle.decentred.util.DecentredUtil; 7 | import net.openhft.chronicle.decentred.util.KeyPair; 8 | import net.openhft.chronicle.salt.Ed25519; 9 | import net.openhft.chronicle.wire.Marshallable; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | final class TradeEventTest { 15 | static { 16 | DtoAliases.addAliases(); 17 | } 18 | 19 | @Test 20 | void marshallable() { 21 | KeyPair keyPair = new KeyPair(17); 22 | 23 | TradeEvent te = new TradeEvent() 24 | .action(Side.BUY) 25 | .currencyPair(CurrencyPair.EURXCL) 26 | .price(1000.0) 27 | .quantity(1000.0) 28 | .orderAddress(DecentredUtil.parseAddress("abcdefghijk")) 29 | .orderTimestampUS(new SetTimeProvider("2018-03-04T18:03:04.264453").currentTimeMicros()) 30 | .protocol(1) 31 | .messageType(1002) 32 | .sign(keyPair.secretKey, new SetTimeProvider("2018-03-04T18:03:05.364453")); 33 | assertEquals("!TradeEvent {\n" + 34 | " timestampUS: 2018-03-04T18:03:05.364453,\n" + 35 | " address: nud6jbceicts2,\n" + 36 | " orderTimestampUS: 2018-03-04T18:03:04.264453,\n" + 37 | " orderAddress: abcdefghijk,\n" + 38 | " quantity: 1E3,\n" + 39 | " price: 1E3,\n" + 40 | " currencyPair: EURXCL,\n" + 41 | " side: BUY\n" + 42 | "}\n", te.toString()); 43 | TradeEvent te2 = Marshallable.fromString(te.toString()); 44 | assertEquals(te2, te); 45 | } 46 | } -------------------------------------------------------------------------------- /examples/exchange/src/test/resources/orders/simpleMatch/in.yaml: -------------------------------------------------------------------------------- 1 | setCurrentTime: 101 2 | --- 3 | newOrderRequest: { 4 | timestampUS: 1970-01-01T00:00:00.1, 5 | address: buyer, 6 | side: BUY, 7 | quantity: 100.0, 8 | maxPrice: 200.0, 9 | currencyPair: USDXCL, 10 | ttlMillis: 100000 11 | } 12 | --- 13 | newOrderRequest: { 14 | timestampUS: 1970-01-01T00:00:00.1, 15 | address: buyer, 16 | side: BUY, 17 | quantity: 100.0, 18 | maxPrice: 199.0, 19 | currencyPair: USDXCL, 20 | ttlMillis: 100000 21 | } 22 | --- 23 | newOrderRequest: { 24 | timestampUS: 1970-01-01T00:00:00.101, 25 | address: buyer, 26 | side: BUY, 27 | quantity: 100.0, 28 | maxPrice: 180.0, 29 | currencyPair: USDXCL, 30 | ttlMillis: 100000 31 | } 32 | --- 33 | newOrderRequest: { 34 | timestampUS: 1970-01-01T00:00:00.102, 35 | address: seller, 36 | side: SELL, 37 | quantity: 100.0, 38 | maxPrice: 210.0, 39 | currencyPair: USDXCL, 40 | ttlMillis: 100000 41 | } 42 | --- 43 | newOrderRequest: { 44 | timestampUS: 1970-01-01T00:00:00.103, 45 | address: seller, 46 | side: SELL, 47 | quantity: 100.0, 48 | maxPrice: 230.0, 49 | currencyPair: USDXCL, 50 | ttlMillis: 100000 51 | } 52 | --- 53 | setCurrentTime: 115 54 | --- 55 | newOrderRequest: { 56 | timestampUS: 1970-01-01T00:00:00.12, 57 | address: buyer, 58 | side: BUY, 59 | quantity: 100.0, 60 | maxPrice: 210.0, 61 | currencyPair: USDXCL, 62 | ttlMillis: 100000 63 | } 64 | --- 65 | setCurrentTime: 215 66 | --- 67 | newOrderRequest: { 68 | timestampUS: 1970-01-01T00:00:00.3, 69 | address: seller, 70 | side: SELL, 71 | quantity: 300.0, 72 | maxPrice: 190.0, 73 | currencyPair: USDXCL, 74 | ttlMillis: 100000 75 | } 76 | --- 77 | exchangeCloseRequest: { 78 | address: master, 79 | reason: End of test 80 | } 81 | -------------------------------------------------------------------------------- /examples/exchange/src/test/resources/orders/simpleMatch/out.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | --- 4 | --- 5 | --- 6 | --- 7 | --- 8 | to: buyer 9 | tradeEvent: { 10 | timestampUS: 1970-01-01T00:00:00.115, 11 | address: ., 12 | orderTimestampUS: 1970-01-01T00:00:00.12, 13 | orderAddress: buyer, 14 | quantity: 100.0, 15 | price: 210.0, 16 | currencyPair: USDXCL, 17 | side: BUY 18 | } 19 | to: seller 20 | tradeEvent: { 21 | timestampUS: 1970-01-01T00:00:00.115, 22 | address: ., 23 | orderTimestampUS: 1970-01-01T00:00:00.102, 24 | orderAddress: seller, 25 | quantity: 100.0, 26 | price: 210.0, 27 | currencyPair: USDXCL, 28 | side: SELL 29 | } 30 | --- 31 | --- 32 | to: seller 33 | tradeEvent: { 34 | timestampUS: 1970-01-01T00:00:00.215, 35 | address: ., 36 | orderTimestampUS: 1970-01-01T00:00:00.3, 37 | orderAddress: seller, 38 | quantity: 100.0, 39 | price: 190.0, 40 | currencyPair: USDXCL, 41 | side: SELL 42 | } 43 | to: buyer 44 | tradeEvent: { 45 | timestampUS: 1970-01-01T00:00:00.215, 46 | address: ., 47 | orderTimestampUS: 1970-01-01T00:00:00.1, 48 | orderAddress: buyer, 49 | quantity: 100.0, 50 | price: 200.0, 51 | currencyPair: USDXCL, 52 | side: BUY 53 | } 54 | to: seller 55 | tradeEvent: { 56 | timestampUS: 1970-01-01T00:00:00.215, 57 | address: ., 58 | orderTimestampUS: 1970-01-01T00:00:00.3, 59 | orderAddress: seller, 60 | quantity: 100.0, 61 | price: 190.0, 62 | currencyPair: USDXCL, 63 | side: SELL 64 | } 65 | to: buyer 66 | tradeEvent: { 67 | timestampUS: 1970-01-01T00:00:00.215, 68 | address: ., 69 | orderTimestampUS: 1970-01-01T00:00:00.1, 70 | orderAddress: buyer, 71 | quantity: 100.0, 72 | price: 199.0, 73 | currencyPair: USDXCL, 74 | side: BUY 75 | } 76 | --- 77 | to: buyer 78 | tradeClosedEvent: { 79 | timestampUS: 1970-01-01T00:00:00.215, 80 | address: ., 81 | orderTimestampUS: 1970-01-01T00:00:00.101, 82 | orderAddress: buyer, 83 | currencyPair: USDXCL, 84 | side: BUY, 85 | orderCloseReason: EXCHANGE_CLOSED 86 | } 87 | to: seller 88 | tradeClosedEvent: { 89 | timestampUS: 1970-01-01T00:00:00.215, 90 | address: ., 91 | orderTimestampUS: 1970-01-01T00:00:00.3, 92 | orderAddress: seller, 93 | currencyPair: USDXCL, 94 | side: SELL, 95 | orderCloseReason: EXCHANGE_CLOSED 96 | } 97 | to: seller 98 | tradeClosedEvent: { 99 | timestampUS: 1970-01-01T00:00:00.215, 100 | address: ., 101 | orderTimestampUS: 1970-01-01T00:00:00.103, 102 | orderAddress: seller, 103 | currencyPair: USDXCL, 104 | side: SELL, 105 | orderCloseReason: EXCHANGE_CLOSED 106 | } 107 | --- -------------------------------------------------------------------------------- /examples/exchange/src/test/resources/orders/simpleMatch/setup.yaml: -------------------------------------------------------------------------------- 1 | exchangeConfig: { 2 | timestampUS: 1970-01-01T00:00:00, 3 | address: config, 4 | currencies: { 5 | ? USDXCL: { tickSize: 1.0 } 6 | } 7 | } 8 | --- -------------------------------------------------------------------------------- /examples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | net.openhft 8 | java-parent-pom 9 | 1.1.23 10 | 11 | 12 | 13 | town.lost 14 | examples 15 | pom 16 | 0.3.0-SNAPSHOT 17 | Chronicle-Decentred/Examples 18 | Chronicle-Decentred Examples 19 | 20 | 21 | appreciation 22 | exchange 23 | 24 | 25 | -------------------------------------------------------------------------------- /rfc/Decentred-Address.adoc: -------------------------------------------------------------------------------- 1 | = Decentred Address 2 | Peter Lawrey 3 | 4 | Chronicle Decentred uses a 64-bit unsigned `long` for addresses of accounts and destinations. Addresses have a range for different purposes 5 | 6 | === Ranges 7 | 8 | An address with a public key requires the address to be the last 8 bytes of the public key (in little endian) 9 | 10 | |=== 11 | | Top 16 bits | Purpose | Public key? | format 12 | | 0x0000 | Temporary connections | no | @IP Address:port 13 | | 0x0001 - 0x00FF | reserved | na 14 | | 0x0100 - 0xDFFF | verified IP address | yes | @IP Address:port:lower bits 15 | | 0xE000 - 0xFFFF | user accounts | yes | @address in base 32 16 | |=== 17 | 18 | === Verified IP address 19 | 20 | The format of an address which can be verified consists of 21 | 22 | - The IPv4 address of the server (top 32-bits) 23 | - The port of the server (next 16-bits) 24 | - Any number which matches the public key (lower 16-bits) 25 | 26 | === User accounts 27 | 28 | User accounts have to have the top 3 bits set to distinguish them 29 | from verified server addresses. 30 | 31 | === Printing addresses. 32 | 33 | Addresses come in three formats 34 | 35 | |=== 36 | | format | example 37 | | IP Address:port | 172.10.11.12:12345 38 | | IP Address:port:lower bit | 172.10.11.12:12345:65432 39 | | base32 address | abcdefghijkl 40 | |=== 41 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/AddressManagementRequests.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.decentred.dto.address.CreateAddressRequest; 5 | 6 | /** 7 | * Allows messages to be passed without needing to be self signing i.e. using just an account. 8 | */ 9 | public interface AddressManagementRequests { 10 | /** 11 | * Attempt to create an account. 12 | * 13 | * @param createAddressRequest to be processed 14 | */ 15 | @MethodId(0xF000) 16 | void createAddressRequest(CreateAddressRequest createAddressRequest); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/AddressManagementResponses.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.core.Jvm; 5 | import net.openhft.chronicle.decentred.dto.address.CreateAddressEvent; 6 | 7 | /** 8 | * Allows messages to be passed without needing to be self signing i.e. using just an account. 9 | */ 10 | public interface AddressManagementResponses { 11 | /** 12 | * Notify that an account was created. 13 | * 14 | * @param createAddressEvent record 15 | */ 16 | @MethodId(0xF080) 17 | default void createAddressEvent(CreateAddressEvent createAddressEvent) { 18 | Jvm.debug().on(getClass(), "Account created " + createAddressEvent); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/BlockEvents.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.decentred.dto.blockevent.EndOfRoundBlockEvent; 5 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockEvent; 6 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockGossipEvent; 7 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockVoteEvent; 8 | 9 | public interface BlockEvents { 10 | 11 | @MethodId(0xFFF0) 12 | void transactionBlockEvent(TransactionBlockEvent transactionBlockEvent); 13 | 14 | @MethodId(0xFFF1) 15 | void transactionBlockGossipEvent(TransactionBlockGossipEvent transactionBlockGossipEvent); 16 | 17 | @MethodId(0xFFF2) 18 | void transactionBlockVoteEvent(TransactionBlockVoteEvent transactionBlockVoteEvent); 19 | 20 | @MethodId(0xFFF3) 21 | void endOfRoundBlockEvent(EndOfRoundBlockEvent endOfRoundBlockEvent); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/BlockchainPhase.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | public enum BlockchainPhase { 4 | INIT, BOOTSTRAP, REPLAY 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/ChainLifecycleRequests.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.decentred.dto.chainlifecycle.AssignDelegatesRequest; 5 | import net.openhft.chronicle.decentred.dto.chainlifecycle.CreateChainRequest; 6 | import net.openhft.chronicle.decentred.dto.chainlifecycle.CreateTokenRequest; 7 | 8 | public interface ChainLifecycleRequests { 9 | 10 | @MethodId(0x0101) 11 | void createChainRequest(CreateChainRequest createChainRequest); 12 | 13 | @MethodId(0x0102) 14 | void assignDelegatesRequest(AssignDelegatesRequest assignDelegatesRequest); 15 | 16 | @MethodId(0x0103) 17 | void createTokenRequest(CreateTokenRequest createTokenRequest); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/ConnectionStatusListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.core.Jvm; 4 | import net.openhft.chronicle.decentred.remote.net.TCPConnection; 5 | 6 | /** 7 | * The framework letting the gateway know a connection has appeared of disappeared. 8 | */ 9 | public interface ConnectionStatusListener { 10 | /** 11 | * Called by the framework on a new connection 12 | * 13 | * @param connection connected 14 | */ 15 | default void onConnection(TCPConnection connection) { 16 | Jvm.debug().on(getClass(), "Connected " + connection); 17 | } 18 | 19 | /** 20 | * Called by the framework on disconnection 21 | * 22 | * @param connection disconnected 23 | */ 24 | default void onDisconnection(TCPConnection connection) { 25 | Jvm.debug().on(getClass(), "Disconnected " + connection); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/MessageListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.SignedMessage; 4 | 5 | public interface MessageListener { 6 | 7 | /** 8 | * Called by the framework on a signed message 9 | * 10 | * @param message connected 11 | */ 12 | void onMessage(SignedMessage message); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/MessageRouter.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 4 | import net.openhft.chronicle.wire.LongConversion; 5 | 6 | public interface MessageRouter { 7 | long DEFAULT_CONNECTION = 0L; 8 | 9 | default T toDefault() { 10 | return to(DEFAULT_CONNECTION); 11 | } 12 | 13 | T to(@LongConversion(AddressLongConverter.class) long address); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/MessageToListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.SignedMessage; 4 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | 7 | public interface MessageToListener { 8 | 9 | void onMessageTo(@LongConversion(AddressLongConverter.class) long address, SignedMessage message); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/SystemMessageListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.core.Jvm; 5 | import net.openhft.chronicle.decentred.dto.error.ApplicationErrorResponse; 6 | 7 | public interface SystemMessageListener extends 8 | AddressManagementResponses, 9 | Verifier, 10 | ConnectionStatusListener { 11 | 12 | /** 13 | * Notify an application error occurred in response to a message passed. 14 | * 15 | * @param applicationErrorResponse occurred 16 | */ 17 | @MethodId(0xFF10) 18 | default void applicationError(ApplicationErrorResponse applicationErrorResponse) { 19 | Jvm.warn().on(getClass(), "Unhandled error " + applicationErrorResponse); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/SystemMessages.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | public interface SystemMessages extends 4 | BlockEvents, 5 | AddressManagementRequests, 6 | ChainLifecycleRequests, 7 | SystemMessageListener {} 8 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/TransactionProcessor.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | public interface TransactionProcessor { 4 | void blockchainPhase(BlockchainPhase blockchainPhase); 5 | 6 | void messageRouter(MessageRouter messageRouter); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/api/Verifier.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.api; 2 | 3 | import net.openhft.chronicle.bytes.MethodId; 4 | import net.openhft.chronicle.decentred.dto.address.InvalidationEvent; 5 | import net.openhft.chronicle.decentred.dto.VerificationEvent; 6 | 7 | public interface Verifier { 8 | 9 | /** 10 | * Sends the provided signed {@code verificationEvent} message. 11 | * 12 | * @param verificationEvent to send 13 | */ 14 | @MethodId(0xF100) 15 | void verificationEvent(VerificationEvent verificationEvent); 16 | 17 | /** 18 | * Sends the provided {@code invalidationEvent} notifying that 19 | * a server was invalidated. 20 | * 21 | * @param invalidationEvent to send 22 | */ 23 | @MethodId(0xF101) 24 | void invalidationEvent(InvalidationEvent invalidationEvent); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/VerificationEvent.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto; 2 | 3 | import net.openhft.chronicle.bytes.*; 4 | import net.openhft.chronicle.decentred.dto.base.SelfSignedMessage; 5 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 6 | import net.openhft.chronicle.decentred.util.DecentredUtil; 7 | import net.openhft.chronicle.salt.Ed25519; 8 | import net.openhft.chronicle.wire.LongConversion; 9 | 10 | /** 11 | * This message states this node verifies a given public key after connecting to it successfully. 12 | * 13 | */ 14 | @Deprecated(/* to be removed in x.22 */) 15 | public class VerificationEvent extends SelfSignedMessage { 16 | 17 | @LongConversion(AddressLongConverter.class) 18 | private long addressVerified; 19 | private Bytes keyVerified = Bytes.allocateElasticDirect(Ed25519.PUBLIC_KEY_LENGTH); 20 | 21 | public long addressVerified() { 22 | return addressVerified; 23 | } 24 | 25 | public VerificationEvent addressVerified(long addressVerified) { 26 | this.addressVerified = addressVerified; 27 | return this; 28 | } 29 | 30 | public VerificationEvent keyVerified(BytesStore key) { 31 | keyVerified.clear().write(key); 32 | addressVerified = DecentredUtil.toAddress(key); 33 | return this; 34 | } 35 | 36 | public BytesStore keyVerified() { 37 | return keyVerified; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/address/CreateAddressEvent.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.address; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | 5 | // Confirms that the CreateAddressRequest was approved 6 | 7 | // The intention is to add a message that can associate an address to a server list (IP-addresses) authorities() 8 | public final class CreateAddressEvent extends VanillaSignedMessage { 9 | 10 | private CreateAddressRequest createAddressRequest; 11 | 12 | public CreateAddressRequest createAddressRequest() { 13 | return createAddressRequest; 14 | } 15 | 16 | public CreateAddressEvent createAddressRequest(CreateAddressRequest createAddressRequest) { 17 | assertNotSigned(); 18 | this.createAddressRequest = createAddressRequest; 19 | return this; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/address/CreateAddressRequest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.address; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.SelfSignedMessage; 4 | 5 | // Test this 6 | // Is more of a Linux account 7 | // Associates a long with a PublicKey (=put(long, publickey) 8 | // Todo: Prevent reuse of public key 9 | // It tests we would like to turn of verification to test same long... 10 | public final class CreateAddressRequest extends SelfSignedMessage {} 11 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/address/InvalidationEvent.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.address; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.SelfSignedMessage; 4 | 5 | /** 6 | * This message states this node verifies a given public key after connecting to it successfully. 7 | */ 8 | // Invalidate an address previously acquired by CreateAddressRequest 9 | // Protect if the keys become known. Seal or archive an account. 10 | // Currently not used 11 | public final class InvalidationEvent extends SelfSignedMessage {} 12 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/DtoAliases.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base; 2 | 3 | import net.openhft.chronicle.core.pool.ClassAliasPool; 4 | import net.openhft.chronicle.decentred.dto.*; 5 | import net.openhft.chronicle.decentred.dto.blockevent.EndOfRoundBlockEvent; 6 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockEvent; 7 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockGossipEvent; 8 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockVoteEvent; 9 | import net.openhft.chronicle.decentred.dto.address.CreateAddressEvent; 10 | import net.openhft.chronicle.decentred.dto.address.CreateAddressRequest; 11 | import net.openhft.chronicle.decentred.dto.chainlifecycle.CreateChainRequest; 12 | import net.openhft.chronicle.decentred.dto.address.InvalidationEvent; 13 | import net.openhft.chronicle.decentred.dto.error.ApplicationErrorResponse; 14 | 15 | public enum DtoAliases { 16 | ; // none 17 | 18 | static { 19 | ClassAliasPool.CLASS_ALIASES.addAlias( 20 | ApplicationErrorResponse.class, 21 | CreateAddressRequest.class, 22 | CreateAddressEvent.class, 23 | CreateChainRequest.class, 24 | InvalidationEvent.class, 25 | TransactionBlockEvent.class, 26 | TransactionBlockGossipEvent.class, 27 | TransactionBlockVoteEvent.class, 28 | EndOfRoundBlockEvent.class, 29 | VerificationEvent.class 30 | ); 31 | } 32 | 33 | public static void addAliases() { 34 | // static init block does everything. 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/EmptyTransientFieldHandler.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base; 2 | 3 | import net.openhft.chronicle.bytes.BytesIn; 4 | import net.openhft.chronicle.bytes.BytesOut; 5 | import net.openhft.chronicle.wire.WireIn; 6 | import net.openhft.chronicle.wire.WireOut; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | /** 10 | * Internal class that provides an implementation of a TransientFieldHandle 11 | * suitable for messages with no transient fields. 12 | * 13 | * @param message type 14 | */ 15 | class EmptyTransientFieldHandler> implements TransientFieldHandler { 16 | 17 | private static final TransientFieldHandler INSTANCE = new EmptyTransientFieldHandler<>(); 18 | 19 | @SuppressWarnings("unchecked") 20 | public static > TransientFieldHandler instance() { 21 | return (TransientFieldHandler) INSTANCE; 22 | } 23 | 24 | private EmptyTransientFieldHandler() {} 25 | 26 | @Override 27 | public void reset(T original) {} 28 | 29 | @Override 30 | public void copyNonMarshalled(@NotNull T original, @NotNull T target) {} 31 | 32 | /* @Override 33 | public void copyNonMarshalled(@NotNull T original, @NotNull T target) {} 34 | 35 | @Override 36 | public void deepCopy(@NotNull T original, @NotNull T target) {}*/ 37 | 38 | @Override 39 | public void writeMarshallable(@NotNull T original, @NotNull WireOut wire) {} 40 | 41 | @Override 42 | public void readMarshallable(T original, @NotNull WireIn wire) {} 43 | 44 | @Override 45 | public void writeMarshallableInternal(T original, BytesOut bytes) {} 46 | 47 | @Override 48 | public void readMarshallable(@NotNull T original, @NotNull BytesIn bytes) {} 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/SelfSignedMessage.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.bytes.BytesStore; 5 | import net.openhft.chronicle.salt.Ed25519; 6 | 7 | /** 8 | * This message states this node verifies a given public key 9 | * after connecting to it successfully. 10 | */ 11 | public abstract class SelfSignedMessage> extends VanillaSignedMessage { 12 | private final Bytes publicKey = Bytes.allocateElasticDirect(Ed25519.PUBLIC_KEY_LENGTH); 13 | 14 | @Override 15 | public boolean hasPublicKey() { 16 | return true; 17 | } 18 | 19 | @Override 20 | public M publicKey(BytesStore key) { 21 | assertNotSigned(); 22 | long offset = key.readLimit() - Ed25519.PUBLIC_KEY_LENGTH; 23 | this.publicKey.clear().write(key, offset, Ed25519.PUBLIC_KEY_LENGTH); 24 | return self(); 25 | } 26 | 27 | public BytesStore publicKey() { 28 | return publicKey; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/SignedMessage.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base; 2 | 3 | import net.openhft.chronicle.bytes.BytesMarshallable; 4 | import net.openhft.chronicle.bytes.BytesStore; 5 | 6 | public interface SignedMessage extends BytesMarshallable { 7 | 8 | /** 9 | * Returns the protocol for this message. 10 | *

11 | * The protocol is stored as an unsigned short 1-65,536) 12 | * 13 | * @return the protocol for this message 14 | */ 15 | int protocol(); 16 | 17 | /** 18 | * Returns the message type for this message. 19 | *

20 | * The message type is stored as an unsigned short (1-65,536) 21 | * 22 | * @return the message type for this message 23 | */ 24 | int messageType(); 25 | 26 | /** 27 | * Returns if this message is signed. 28 | * 29 | * Once a message is signed it can't be modified, only read. 30 | *

31 | * It cannot be sent until it is signed. 32 | * 33 | * @return true if signed, false if not signed 34 | */ 35 | boolean signed(); 36 | 37 | /** 38 | * Returns a unique address for the sender. This should be the last 8 bytes of the public key. 39 | * 40 | * @return a unique id for this server. 41 | */ 42 | long address(); 43 | 44 | /** 45 | * Returns a microsecond precision, unique monotonically increasing timestamp 46 | *

47 | * NOTE: If the writing system doesn't have a micro-second accurate clock, 48 | * the most accurate clock should be used and increment the timestamp in the cause of any collision 49 | * 50 | * @return a unique microsecond timestamp for an address. Must be monotonically increasing. 51 | */ 52 | long timestampUS(); 53 | 54 | /** 55 | * Returns the public key if it is embedded in the message. If no such public key is embedded, returns a ByteStore 56 | * of length zero. 57 | * 58 | * @return the public key if it is embedded in the message. 59 | */ 60 | BytesStore publicKey(); 61 | 62 | /** 63 | * Signs and returns this message. As an additional side effect, also sets 64 | * the public key (if any) and address in this message. 65 | * 66 | * @param secretKey to sign this message with. 67 | * @return this signed message 68 | * @throws NullPointerException if the provided {@code secretKey} is {@code null} 69 | */ 70 | SignedMessage sign(BytesStore secretKey); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/trait/HasAddressToBlockNumberMap.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base.trait; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.LongLongMap; 5 | 6 | public interface HasAddressToBlockNumberMap> { 7 | 8 | /** 9 | * Returns the address to block number map for this message. 10 | *

11 | * The returned map is mutable. 12 | * 13 | * @return the address to block number map for this message 14 | */ 15 | LongLongMap addressToBlockNumberMap(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/trait/HasBlockNumber.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base.trait; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | 5 | public interface HasBlockNumber> { 6 | 7 | /** 8 | * Returns the block number for this message. 9 | * 10 | * @return the block number for this message 11 | */ 12 | long blockNumber(); 13 | 14 | /** 15 | * Sets the block number for this message. 16 | *

17 | * The block number must be non-negative. 18 | * 19 | * @param blockNumber used for setting this message's block number 20 | * 21 | * @return this message including the newly updated 22 | * block number 23 | */ 24 | T blockNumber(long blockNumber); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/trait/HasChainAddress.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base.trait; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | 5 | public interface HasChainAddress> { 6 | 7 | /** 8 | * Returns the chain address for this message. 9 | * 10 | * @return the chain address for this message 11 | */ 12 | long chainAddress(); 13 | 14 | /** 15 | * Sets the chain address for this message. 16 | *

17 | * A chain address uniquely identifies a chain. 18 | * 19 | * @param chainAddress used for setting this message's chain address 20 | * 21 | * @return this message including the newly updated 22 | * chain address 23 | */ 24 | T chainAddress(long chainAddress); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/trait/HasDtoParser.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base.trait; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.DtoParser; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | /** 8 | * Signifies that this message has a {@link DtoParser}. 9 | * 10 | * @param message type 11 | * @param DtoParser union messages type 12 | */ 13 | public interface HasDtoParser, U> { 14 | 15 | /** 16 | * Returns the {@link DtoParser} for this message. 17 | * 18 | * @return the {@link DtoParser} for this message 19 | */ 20 | DtoParser dtoParser(); 21 | 22 | /** 23 | * Sets the {@link DtoParser} for this message. 24 | * 25 | * @param dtoParser to use for setting 26 | * @return this instance 27 | * 28 | * @throws NullPointerException if the provided {@code dtoParser} 29 | * is {@code null} 30 | */ 31 | T dtoParser(@NotNull DtoParser dtoParser); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/trait/HasTransientFieldHandler.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base.trait; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.TransientFieldHandler; 4 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 5 | 6 | public interface HasTransientFieldHandler> { 7 | 8 | TransientFieldHandler transientFieldHandler(); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/base/trait/HasWeekNumber.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.base.trait; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | 5 | public interface HasWeekNumber> { 6 | 7 | /** 8 | * Returns the week number for this message. 9 | * 10 | * @return the week number for this message 11 | */ 12 | int weekNumber(); 13 | 14 | /** 15 | * Sets the week number for this message. 16 | *

17 | * The provided {@code weekNumber} must be non-negative and 18 | * smaller or equal to 65,536 19 | * 20 | * @param weekNumber used for setting this message's week number 21 | * 22 | * @return this message including the newly updated 23 | * week number 24 | */ 25 | T weekNumber(int weekNumber); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/chainlifecycle/CreateChainRequest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.chainlifecycle; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.decentred.util.OffsetIntConverter; 5 | import net.openhft.chronicle.wire.IntConversion; 6 | 7 | // Dynamic lifecycle of a chain 8 | // One chain per address 9 | // private int cycleOffset; private int roundsPerDay; ignored as of now 10 | 11 | //Create address -> CreateChain -> Delegate Chain 12 | 13 | public final class CreateChainRequest extends VanillaSignedMessage { 14 | 15 | @IntConversion(OffsetIntConverter.class) 16 | private int cycleOffset; 17 | private int roundsPerDay; 18 | 19 | public int cycleOffset() { 20 | return cycleOffset; 21 | } 22 | 23 | public CreateChainRequest cycleOffset(int cycleOffset) { 24 | assertNotSigned(); 25 | this.cycleOffset = cycleOffset; 26 | return this; 27 | } 28 | 29 | public int roundsPerDay() { 30 | return roundsPerDay; 31 | } 32 | 33 | public CreateChainRequest roundsPerDay(int roundsPerDay) { 34 | assertNotSigned(); 35 | this.roundsPerDay = roundsPerDay; 36 | return this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/dto/chainlifecycle/CreateTokenRequest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.chainlifecycle; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 4 | import net.openhft.chronicle.wire.Base85LongConverter; 5 | import net.openhft.chronicle.wire.LongConversion; 6 | 7 | // Once a chain then create a token associated to the chaine. Any number N 8 | // The "type" of the chain. 9 | // Shares, Permissions, Fixed value chains 10 | public final class CreateTokenRequest extends VanillaSignedMessage { 11 | 12 | @LongConversion(Base85LongConverter.class) 13 | private long symbol; // 1..10 characters 14 | private double amount; // How much this chain can hold like 10M MyMoney 15 | private double granularity; // 0.01 e.g. cents 16 | 17 | public long symbol() { 18 | return symbol; 19 | } 20 | 21 | // At least X characters, where X is perhaps 1 22 | public CreateTokenRequest symbol(long symbol) { 23 | assertNotSigned(); 24 | this.symbol = symbol; 25 | return this; 26 | } 27 | 28 | public double amount() { 29 | return amount; 30 | } 31 | 32 | public CreateTokenRequest amount(double amount) { 33 | assertNotSigned(); 34 | this.amount = amount; 35 | return this; 36 | } 37 | 38 | public double granularity() { 39 | return granularity; 40 | } 41 | 42 | public CreateTokenRequest granularity(double granularity) { 43 | assertNotSigned(); 44 | if (granularity < 0.0) { 45 | throw new IllegalArgumentException("Granularity must be positive: " + granularity); 46 | } 47 | 48 | this.granularity = granularity; 49 | return this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/internal/server/MultiMessageToListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.internal.server; 2 | 3 | import net.openhft.chronicle.core.Maths; 4 | import net.openhft.chronicle.decentred.api.MessageToListener; 5 | import net.openhft.chronicle.decentred.dto.base.SignedMessage; 6 | import net.openhft.chronicle.decentred.server.RunningMessageToListener; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | import java.util.stream.IntStream; 12 | import java.util.stream.Stream; 13 | 14 | import static java.util.stream.Collectors.collectingAndThen; 15 | import static java.util.stream.Collectors.toList; 16 | 17 | public final class MultiMessageToListener implements RunningMessageToListener { 18 | 19 | private final SingleMessageToListener[] messageWriters; 20 | private final List runnables; 21 | private final int mask; 22 | 23 | public MultiMessageToListener(int count, @NotNull MessageToListener server) { 24 | count = Maths.nextPower2(count, 2); 25 | this.mask = count - 1; 26 | messageWriters = IntStream.range(0, count) 27 | .mapToObj(i -> new SingleMessageToListener(server)) 28 | .toArray(SingleMessageToListener[]::new); 29 | runnables = Stream.of(messageWriters) 30 | .map(Runnable.class::cast) 31 | .collect(collectingAndThen(toList(), Collections::unmodifiableList)); 32 | } 33 | 34 | @Override 35 | public void onMessageTo(long address, SignedMessage message) { 36 | messageWriters[(int) (Maths.agitate(address) & mask)].onMessageTo(address, message); 37 | } 38 | 39 | @Override 40 | public List runnables() { 41 | return runnables; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/internal/server/QueuingChainer.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.internal.server; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.SignedMessage; 4 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockEvent; 5 | import net.openhft.chronicle.decentred.server.Chainer; 6 | import net.openhft.chronicle.decentred.util.DtoRegistry; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | public final class QueuingChainer implements Chainer { 13 | 14 | private final List messages = new ArrayList<>(); 15 | private final long chainAddress; 16 | private final DtoRegistry dtoRegistry; 17 | 18 | public QueuingChainer(long chainAddress, @NotNull DtoRegistry dtoRegistry) { 19 | this.dtoRegistry = dtoRegistry; 20 | this.chainAddress = chainAddress; 21 | } 22 | 23 | @Override 24 | public void onMessage(SignedMessage message) { 25 | synchronized (messages) { 26 | messages.add(message); 27 | } 28 | } 29 | 30 | public TransactionBlockEvent nextTransactionBlockEvent() { 31 | synchronized (messages) { 32 | if (messages.isEmpty()) { 33 | return null; 34 | } 35 | 36 | @SuppressWarnings("unchecked") 37 | final TransactionBlockEvent tbe = ((TransactionBlockEvent) dtoRegistry.create(TransactionBlockEvent.class)) 38 | .chainAddress(chainAddress) 39 | .dtoParser(dtoRegistry.get()); 40 | 41 | messages.forEach(tbe::addTransaction); 42 | messages.clear(); 43 | return tbe; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/internal/server/VanillaChainer.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.internal.server; 2 | 3 | import net.openhft.chronicle.decentred.dto.base.SignedMessage; 4 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockEvent; 5 | import net.openhft.chronicle.decentred.server.Chainer; 6 | import net.openhft.chronicle.decentred.util.DtoRegistry; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public final class VanillaChainer implements Chainer { 10 | 11 | private final Object transactionLock = new Object(); 12 | private TransactionBlockEvent tbe; 13 | private TransactionBlockEvent tbe2; 14 | 15 | public VanillaChainer(long chainAddress, @NotNull DtoRegistry dtoRegistry) { 16 | tbe = create(chainAddress, dtoRegistry); 17 | tbe2 = create(chainAddress, dtoRegistry); 18 | } 19 | 20 | @Override 21 | public void onMessage(SignedMessage message) { 22 | synchronized (transactionLock) { 23 | // System.out.println("Add "+message); 24 | tbe.addTransaction(message); 25 | } 26 | } 27 | 28 | public TransactionBlockEvent nextTransactionBlockEvent() { 29 | final TransactionBlockEvent tbeToSend; 30 | synchronized (transactionLock) { 31 | // System.out.println(System.currentTimeMillis()+" TBE count "+tbe.count()); 32 | if (tbe.isEmpty()) 33 | return null; 34 | tbeToSend = tbe; 35 | tbe = tbe2; 36 | tbe2 = tbeToSend; 37 | tbe.reset(); 38 | } 39 | return tbeToSend; 40 | } 41 | 42 | private TransactionBlockEvent create(long chainAddress, @NotNull DtoRegistry dtoRegistry) { 43 | @SuppressWarnings("unchecked") final TransactionBlockEvent tbe = ((TransactionBlockEvent) dtoRegistry.create(TransactionBlockEvent.class)) 44 | .chainAddress(chainAddress) 45 | .dtoParser(dtoRegistry.get()); 46 | return tbe; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/internal/unmodifiable/ThrowUtil.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.internal.unmodifiable; 2 | 3 | enum ThrowUtil { 4 | ; // none 5 | 6 | static UnsupportedOperationException newUnsupportedOperationException() { 7 | return new UnsupportedOperationException("This Container is unmodifiable."); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/internal/unmodifiable/UnmodifiableLongCursor.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.internal.unmodifiable; 2 | 3 | import com.koloboke.collect.LongCursor; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import javax.annotation.Nonnull; 7 | import java.util.function.LongConsumer; 8 | 9 | import static net.openhft.chronicle.decentred.internal.unmodifiable.ThrowUtil.newUnsupportedOperationException; 10 | 11 | public final class UnmodifiableLongCursor implements LongCursor { 12 | 13 | private final LongCursor inner; 14 | 15 | public UnmodifiableLongCursor(@NotNull LongCursor inner) { 16 | this.inner = inner; 17 | } 18 | 19 | @Override public void forEachForward(@Nonnull LongConsumer action) { inner.forEachForward(action); } 20 | @Override public long elem() { return inner.elem(); } 21 | @Override public boolean moveNext() { return inner.moveNext(); } 22 | @Override public void remove() { throw newUnsupportedOperationException(); } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/internal/util/ShortUtil.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.internal.util; 2 | 3 | public enum ShortUtil { 4 | ; // none 5 | 6 | private static int MAX_UNSIGNED_VALUE = (1 << Short.SIZE) - 1; 7 | 8 | /** 9 | * Checks that the specified int can be represented by an unsigned short. This 10 | * method is designed primarily for doing parameter validation in methods 11 | * and constructors, as demonstrated below: 12 | *

13 |      * public Foo(int bar) {
14 |      *     this.bar = ShortUtil.requireUnsignedShort(bar);
15 |      * }
16 |      * 
17 | * 18 | * @param value the int value to check range for 19 | * @return the int value if in range 20 | * @throws ArithmeticException if {@code int} is out of range 21 | */ 22 | public static int requireUnsignedShort(int value) { 23 | if (value < 0 || value > MAX_UNSIGNED_VALUE) { 24 | throw new ArithmeticException("unsigned short overflow"); 25 | } 26 | return value; 27 | } 28 | 29 | /** 30 | * Checks that the specified int can be represented by a positive unsigned short. This 31 | * method is designed primarily for doing parameter validation in methods 32 | * and constructors, as demonstrated below: 33 | *
34 |      * public Foo(int bar) {
35 |      *     this.bar = ShortUtil.requirePositiveUnsignedShort(bar);
36 |      * }
37 |      * 
38 | * 39 | * @param value the int value to check range for 40 | * @return the int value if in range 41 | * @throws ArithmeticException if {@code int} is out of range or 42 | * not positive 43 | */ 44 | public static int requirePositiveUnsignedShort(int value) { 45 | if (value <= 0) { 46 | throw new ArithmeticException("value is not positive"); 47 | } 48 | if (value > MAX_UNSIGNED_VALUE) { 49 | throw new ArithmeticException("unsigned short overflow"); 50 | } 51 | return value; 52 | } 53 | 54 | /** 55 | * Returns the value of the {@code int} argument; 56 | * throwing an exception if the value overflows a {@code short}. 57 | * 58 | * @param value the int value 59 | * @return the argument as a short 60 | * @throws ArithmeticException if the {@code argument} overflows a short 61 | */ 62 | public static short toShortExact(int value) { 63 | if ((short) value != value) { 64 | throw new ArithmeticException("short overflow"); 65 | } 66 | return (short) value; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/remote/net/TCPClientListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.net; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | 5 | import java.io.IOException; 6 | import java.nio.channels.SocketChannel; 7 | 8 | public interface TCPClientListener { 9 | default void onClosedChannel(TCPConnection client) { 10 | 11 | } 12 | 13 | default void onNewConnection(TCPConnection client, SocketChannel channel) { 14 | 15 | } 16 | 17 | void onMessage(TCPConnection client, Bytes bytes) throws IOException; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/remote/net/TCPConnection.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.net; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.core.io.Closeable; 5 | 6 | import java.io.IOException; 7 | import java.nio.ByteBuffer; 8 | 9 | public interface TCPConnection extends Closeable { 10 | int MAX_MESSAGE_SIZE = 1 << 20; 11 | int HEADER_LENGTH = 4; 12 | 13 | void write(BytesStore bytes) throws IOException; 14 | 15 | void write(ByteBuffer buffer) throws IOException; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/remote/net/TCPServer.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.net; 2 | 3 | import net.openhft.chronicle.core.io.Closeable; 4 | 5 | public interface TCPServer extends Closeable { 6 | int getPort(); 7 | 8 | TCPServerConnectionListener connectionListener(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/remote/net/TCPServerConnectionListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.net; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | 5 | import java.io.IOException; 6 | import java.net.SocketException; 7 | import java.nio.channels.SocketChannel; 8 | 9 | @FunctionalInterface 10 | public interface TCPServerConnectionListener { 11 | default void onNewConnection(TCPServer server, C channel) { 12 | 13 | } 14 | 15 | default void onClosedConnection(TCPServer server, C channel) { 16 | 17 | } 18 | 19 | default C createConnection(TCPServer server, SocketChannel accept) throws SocketException { 20 | return (C) new VanillaTCPServerConnection(server, accept); 21 | } 22 | 23 | void onMessage(TCPServer server, C channel, Bytes bytes) throws IOException; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/remote/net/VanillaTCPServerConnection.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.net; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.core.Jvm; 5 | 6 | import java.io.EOFException; 7 | import java.io.IOException; 8 | import java.net.SocketException; 9 | import java.nio.ByteBuffer; 10 | import java.nio.ByteOrder; 11 | import java.nio.channels.SocketChannel; 12 | 13 | public class VanillaTCPServerConnection extends AbstractTCPConnection implements Runnable { 14 | private final TCPServer tcpServer; 15 | 16 | public VanillaTCPServerConnection(TCPServer tcpServer, SocketChannel channel) throws SocketException { 17 | super(channel); 18 | this.tcpServer = tcpServer; 19 | channel.socket().setSendBufferSize(1 << 20); 20 | channel.socket().setReceiveBufferSize(2 << 20); 21 | // channel.socket().setTcpNoDelay(true); 22 | } 23 | 24 | private static ByteBuffer[] createHeaderArray() { 25 | ByteBuffer header = ByteBuffer.allocateDirect(4).order(ByteOrder.LITTLE_ENDIAN); 26 | ByteBuffer[] ret = {header, null}; 27 | return ret; 28 | } 29 | 30 | @Override 31 | public void run() { throwExceptionIfClosed(); 32 | 33 | try { 34 | tcpServer.connectionListener().onNewConnection(tcpServer, this); 35 | Bytes readBytes = Bytes.elasticByteBuffer(MAX_MESSAGE_SIZE); 36 | 37 | while (running) { 38 | readChannel(readBytes); 39 | } 40 | } catch (EOFException eof) { 41 | // connection closed 42 | } catch (Throwable t) { 43 | Jvm.pause(1); 44 | if (running) 45 | t.printStackTrace(); 46 | 47 | } finally { 48 | tcpServer.connectionListener().onClosedConnection(tcpServer, this); 49 | } 50 | } 51 | 52 | @Override 53 | protected void waitForReconnect() { 54 | // never reconnects 55 | } 56 | 57 | @Override 58 | protected void onMessage(Bytes bytes) throws IOException { 59 | tcpServer.connectionListener().onMessage(tcpServer, this, bytes); 60 | } 61 | 62 | @Override 63 | protected void close2() { 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/BlockEngine.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.core.time.TimeProvider; 5 | import net.openhft.chronicle.decentred.api.MessageListener; 6 | import net.openhft.chronicle.decentred.api.MessageToListener; 7 | import net.openhft.chronicle.decentred.api.SystemMessages; 8 | import net.openhft.chronicle.decentred.internal.server.VanillaBlockEngine; 9 | import net.openhft.chronicle.decentred.server.trait.HasTcpMessageListener; 10 | import net.openhft.chronicle.decentred.util.DecentredUtil; 11 | import net.openhft.chronicle.decentred.util.DtoRegistry; 12 | import net.openhft.chronicle.decentred.util.KeyPair; 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | import java.util.stream.LongStream; 16 | 17 | public interface BlockEngine extends SystemMessages, MessageListener, HasTcpMessageListener { 18 | 19 | void start(MessageToListener messageToListener); 20 | 21 | // Used for testing. 22 | void processOneBlock(); 23 | 24 | static BlockEngine newMain(@NotNull DtoRegistry dtoRegistry, 25 | KeyPair keyPair, 26 | int periodMS, 27 | long[] clusterAddresses, 28 | @NotNull T postBlockChainProcessor, 29 | @NotNull TimeProvider timeProvider) { 30 | 31 | assert LongStream.of(clusterAddresses).distinct().count() == clusterAddresses.length; 32 | long main = DecentredUtil.parseAddress("main"); 33 | return new VanillaBlockEngine<>(dtoRegistry, keyPair, main, periodMS, postBlockChainProcessor, clusterAddresses, timeProvider); 34 | } 35 | 36 | static BlockEngine newLocal(@NotNull DtoRegistry dtoRegistry, 37 | KeyPair keyPair, 38 | long chainAddress, 39 | int periodMS, 40 | long[] clusterAddresses, 41 | @NotNull T postBlockChainProcessor, 42 | @NotNull TimeProvider timeProvider) { 43 | 44 | assert LongStream.of(clusterAddresses).distinct().count() == clusterAddresses.length; 45 | return new VanillaBlockEngine<>(dtoRegistry, keyPair, chainAddress, periodMS, postBlockChainProcessor, clusterAddresses, timeProvider); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/BlockReplayer.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.decentred.dto.blockevent.EndOfRoundBlockEvent; 4 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockEvent; 5 | 6 | public interface BlockReplayer { 7 | 8 | void transactionBlockEvent(TransactionBlockEvent transactionBlockEvent); 9 | 10 | void endOfRoundBlockEvent(EndOfRoundBlockEvent endOfRoundBlockEvent); 11 | 12 | void replayBlocks(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/DecentredServer.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageRouter; 4 | import net.openhft.chronicle.decentred.api.MessageToListener; 5 | import net.openhft.chronicle.decentred.util.AddressLongConverter; 6 | import net.openhft.chronicle.decentred.util.PublicKeyRegistry; 7 | import net.openhft.chronicle.wire.LongConversion; 8 | 9 | public interface DecentredServer extends MessageRouter, MessageToListener, PublicKeyRegistry { 10 | void subscribe(@LongConversion(AddressLongConverter.class) long address); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/Gateway.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.core.io.Closeable; 4 | import net.openhft.chronicle.decentred.api.ConnectionStatusListener; 5 | import net.openhft.chronicle.decentred.api.SystemMessages; 6 | 7 | public interface Gateway extends SystemMessages, Closeable, ConnectionStatusListener { 8 | void start(DecentredServer decentredServer); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/GatewayConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.core.time.TimeProvider; 4 | import net.openhft.chronicle.decentred.util.DtoRegistry; 5 | import net.openhft.chronicle.decentred.util.KeyPair; 6 | 7 | public interface GatewayConfiguration { 8 | DtoRegistry dtoRegistry(); 9 | KeyPair keyPair(); 10 | String regionStr(); 11 | long[] clusterAddresses(); 12 | int mainPeriodMS(); 13 | int localPeriodMS(); 14 | TimeProvider timeProvider(); 15 | 16 | static GatewayConfiguration of ( 17 | DtoRegistry dtoRegistry, 18 | KeyPair keyPair, 19 | String region, 20 | long[] clusterAddressArray, 21 | int mainBlockPeriodMS, 22 | int localBlockPeriodMS, 23 | TimeProvider timeProvider 24 | ) { 25 | return new GatewayConfiguration() { 26 | @Override 27 | public DtoRegistry dtoRegistry() { 28 | return dtoRegistry; 29 | } 30 | 31 | @Override 32 | public KeyPair keyPair() { 33 | return keyPair; 34 | } 35 | 36 | @Override 37 | public String regionStr() { 38 | return region; 39 | } 40 | 41 | @Override 42 | public long[] clusterAddresses() { 43 | return clusterAddressArray; 44 | } 45 | 46 | @Override 47 | public int mainPeriodMS() { 48 | return mainBlockPeriodMS; 49 | } 50 | 51 | @Override 52 | public int localPeriodMS() { 53 | return localBlockPeriodMS; 54 | } 55 | 56 | @Override 57 | public TimeProvider timeProvider() { 58 | return timeProvider; 59 | } 60 | }; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/Gossiper.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockEvent; 4 | 5 | public interface Gossiper { 6 | 7 | /** 8 | * Receives a TransactionBlockEvent from a 999 node. 9 | * 10 | * @param transactionBlockEvent to receive 11 | */ 12 | void transactionBlockEvent(TransactionBlockEvent transactionBlockEvent); 13 | 14 | /** 15 | * Instructs this Gossiper to send a TransactionBlockGossipEvent for the provided 16 | * {@code blockNumber} to a Voter 17 | * 18 | * @param blockNumber to use 19 | */ 20 | void sendGossip(long blockNumber); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/RunningMessageToListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageToListener; 4 | import net.openhft.chronicle.decentred.internal.server.MultiMessageToListener; 5 | import net.openhft.chronicle.decentred.internal.server.SingleMessageToListener; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.util.List; 9 | 10 | public interface RunningMessageToListener extends MessageToListener { 11 | 12 | List runnables(); 13 | 14 | static RunningMessageToListener createSingle(@NotNull MessageToListener server) { 15 | return new SingleMessageToListener(server); 16 | } 17 | 18 | static RunningMessageToListener createMulti(int count, @NotNull MessageToListener server) { 19 | return new MultiMessageToListener(count, server); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/VanillaVerifyIP.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.decentred.api.ConnectionStatusListener; 5 | import net.openhft.chronicle.decentred.api.MessageRouter; 6 | import net.openhft.chronicle.decentred.api.Verifier; 7 | import net.openhft.chronicle.decentred.dto.address.InvalidationEvent; 8 | import net.openhft.chronicle.decentred.dto.VerificationEvent; 9 | import net.openhft.chronicle.decentred.remote.net.TCPConnection; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | import static net.openhft.chronicle.decentred.api.MessageRouter.DEFAULT_CONNECTION; 17 | 18 | public class VanillaVerifyIP implements Verifier, ConnectionStatusListener { 19 | private final MessageRouter client; 20 | private final Map> verifyMap = new HashMap<>(); 21 | 22 | public VanillaVerifyIP(MessageRouter client) { 23 | this.client = client; 24 | } 25 | 26 | @Override 27 | public void onConnection(TCPConnection connection) { 28 | Verifier to = client.to(DEFAULT_CONNECTION); 29 | for (List verificationEventList : verifyMap.values()) { 30 | for (VerificationEvent verificationEvent : verificationEventList) { 31 | to.verificationEvent(verificationEvent); 32 | } 33 | } 34 | } 35 | 36 | @Override 37 | public void verificationEvent(VerificationEvent verificationEvent) { 38 | List verificationEventList = verifyMap.computeIfAbsent(verificationEvent.keyVerified(), k -> new ArrayList<>()); 39 | // TODO check it is not already in the list. 40 | VerificationEvent v2 = verificationEvent.deepCopy(); 41 | verificationEventList.add(v2); 42 | client.to(DEFAULT_CONNECTION) 43 | .verificationEvent(verificationEvent); 44 | } 45 | 46 | @Override 47 | public void invalidationEvent(InvalidationEvent invalidationEvent) { 48 | verifyMap.remove(invalidationEvent.publicKey()); 49 | client.to(DEFAULT_CONNECTION) 50 | .invalidationEvent(invalidationEvent); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/VoteTaker.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockVoteEvent; 5 | import net.openhft.chronicle.decentred.internal.server.VanillaVoteTaker; 6 | import net.openhft.chronicle.decentred.server.trait.HasTcpMessageListener; 7 | import net.openhft.chronicle.decentred.util.DtoRegistry; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | public interface VoteTaker extends HasTcpMessageListener { 11 | 12 | /** 13 | * Receives a TransactionBlockVoteEvent from a Voter. 14 | * 15 | * @param transactionBlockVoteEvent vote to consider 16 | */ 17 | void transactionBlockVoteEvent(@NotNull TransactionBlockVoteEvent transactionBlockVoteEvent); 18 | 19 | /** 20 | * Returns if this VoteTake has a majority vote. 21 | * 22 | * @return if this VoteTake has a majority vote 23 | */ 24 | boolean hasMajority(); 25 | 26 | /** 27 | * Instructs this VoteTaker to send a EndOfRoundBlockEvent for the provided 28 | * {@code blockNumber} 29 | * 30 | * @param blockNumber to use 31 | * 32 | * @return if at least one block event was replayed, false otherwise 33 | */ 34 | boolean sendEndOfRoundBlock(long blockNumber); 35 | 36 | @NotNull 37 | static VoteTaker create(long address, 38 | long chainAddress, 39 | @NotNull long[] clusterAddresses, 40 | @NotNull BlockReplayer replayer, 41 | @NotNull BytesStore secretKey, 42 | @NotNull DtoRegistry dtoRegistry) { 43 | return new VanillaVoteTaker(address, chainAddress, clusterAddresses, replayer, secretKey, dtoRegistry); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/Voter.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockGossipEvent; 5 | import net.openhft.chronicle.decentred.internal.server.LastGossipVoter; 6 | import net.openhft.chronicle.decentred.server.trait.HasTcpMessageListener; 7 | import net.openhft.chronicle.decentred.util.DtoRegistry; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | public interface Voter extends HasTcpMessageListener { 11 | 12 | /** 13 | * Receives a TransactionBlockGossipEvent from a Gossiper. 14 | * 15 | * @param transactionBlockGossipEvent to receive 16 | */ 17 | void transactionBlockGossipEvent(@NotNull TransactionBlockGossipEvent transactionBlockGossipEvent); 18 | 19 | /** 20 | * Instructs this Voter to send a vote for the provided 21 | * {@code blockNumber} 22 | * 23 | * @param blockNumber to use 24 | */ 25 | void sendVote(long blockNumber); 26 | 27 | @NotNull 28 | static Voter createLastGossipVoter(long address, 29 | @NotNull long[] clusterAddresses, 30 | @NotNull VoteTaker voteTaker, 31 | @NotNull BytesStore secretKey, 32 | @NotNull DtoRegistry dtoRegistry) { 33 | return new LastGossipVoter(address, clusterAddresses, voteTaker, secretKey, dtoRegistry); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/server/trait/HasTcpMessageListener.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server.trait; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageToListener; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public interface HasTcpMessageListener { 7 | 8 | /** 9 | * Sets the TCP Message Listener for this object. 10 | * 11 | * @param messageToListener to set 12 | */ 13 | void tcpMessageListener(@NotNull MessageToListener messageToListener); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/AddressLongConverter.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.wire.LongConverter; 4 | 5 | public class AddressLongConverter implements LongConverter { 6 | @Override 7 | public long parse(CharSequence text) { 8 | return DecentredUtil.parseAddress(text); 9 | } 10 | 11 | @Override 12 | public void append(StringBuilder text, long value) { 13 | DecentredUtil.appendAddress(text, value); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/DecentredUtil.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.bytes.BytesStore; 5 | import net.openhft.chronicle.salt.Ed25519; 6 | 7 | public enum DecentredUtil { 8 | ; // none 9 | public static final long MASK_32 = 0x0000_0000_FFFF_FFFFL; 10 | public static final int MASK_16 = 0xFFFF; 11 | 12 | public static long parseAddress(CharSequence text) { 13 | return LetterBase32.decode(text); 14 | } 15 | 16 | public static long toAddress(BytesStore publicKey) { 17 | return publicKey.readLong(publicKey.readLimit() - Long.BYTES); 18 | } 19 | 20 | public static String toAddressString(long address) { 21 | StringBuilder sb = new StringBuilder(13); 22 | appendAddress(sb, address); 23 | return sb.toString(); 24 | } 25 | 26 | public static void appendAddress(StringBuilder text, long value) { 27 | base32(text, value); 28 | } 29 | 30 | private static void base32(StringBuilder text, long value) { 31 | LetterBase32.encode(text, value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/DtoParselet.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.bytes.BytesIn; 4 | import net.openhft.chronicle.core.util.ObjectUtils; 5 | import net.openhft.chronicle.decentred.dto.base.VanillaSignedMessage; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | class DtoParselet { 11 | private final Method method; 12 | private final int protocol; 13 | private final int midValue; 14 | private final Object[] vsmArr = {null}; 15 | private final VanillaSignedMessage vsm; 16 | 17 | public DtoParselet(@NotNull Method method, int protocol, int midValue) { 18 | this.method = method; 19 | this.protocol = protocol; 20 | this.midValue = midValue; 21 | this.vsm = createVSM(method, protocol, midValue); 22 | vsmArr[0] = vsm; 23 | } 24 | 25 | public DtoParselet(@NotNull DtoParselet parselet) { 26 | this.method = parselet.method; 27 | this.protocol = parselet.protocol; 28 | this.midValue = parselet.midValue; 29 | try { 30 | this.vsm = createVSM(method, protocol, midValue); 31 | vsmArr[0] = vsm; 32 | } catch (Exception e) { 33 | throw new AssertionError(e); 34 | } 35 | } 36 | 37 | @NotNull 38 | private static VanillaSignedMessage createVSM(Method method, int protocol, int messageType) { 39 | @SuppressWarnings("unchecked") 40 | final Class type = (Class) method.getParameterTypes()[0]; 41 | final VanillaSignedMessage vsm = ObjectUtils.newInstance(type); 42 | return vsm.protocol(protocol).messageType(messageType); 43 | } 44 | 45 | public void parse(BytesIn bytes, T listener) { 46 | vsm.readMarshallable(bytes); 47 | try { 48 | /* System.out.println(String.format("Parslet invoking %s.%s(%s)%n", 49 | listener.getClass().getName(), 50 | method.getName(), 51 | method.getParameterTypes()[0].getSimpleName()) 52 | ); */ 53 | method.invoke(listener, vsmArr); 54 | } catch (Exception e) { 55 | throw new IllegalStateException(e); 56 | } 57 | } 58 | 59 | public Object parse(BytesIn bytes) { 60 | vsm.readMarshallable(bytes); 61 | return vsm; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return "DtoParselet{" + 67 | "method=" + method + 68 | ", protocol=" + protocol + 69 | ", midValue=" + midValue + 70 | ", vsm=" + vsm + 71 | '}'; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/DtoParser.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.bytes.BytesIn; 4 | import net.openhft.chronicle.decentred.dto.base.SignedMessage; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public interface DtoParser 8 | extends HasSuperInterface { 9 | 10 | /** 11 | * Parses one data transfer object (dto) from the provided {@code bytes} and 12 | * subsequently invokes the provided {@code listener} using the parsed 13 | * dto. 14 | *

15 | * The read position of the provided {@code bytes} is not affected. 16 | *

17 | * If the method is unable to parse a dto, the listener is never invoked 18 | * 19 | * @param bytes to use for parsing the dto 20 | * @param listener to invoke once the dto is parsed 21 | * 22 | * @throws NullPointerException if any of the provided parameters 23 | * are {@code null} 24 | * 25 | */ 26 | void parseOne(@NotNull BytesIn bytes, @NotNull U listener); 27 | 28 | /** 29 | * Parse one object return the message as an object. 30 | * 31 | * @param bytes to use for parsing the dto 32 | * @return the object. 33 | */ 34 | SignedMessage parseOne(@NotNull BytesIn bytes); 35 | 36 | /** 37 | * Invokes a method on the given {@code component} with the given {@code message} 38 | * as an argument. The invocation method is determined using the class of the 39 | * message. 40 | *

41 | * If the method cannot be found or if the invocation fails, the method 42 | * is never invoked. 43 | * 44 | * @param component on which to invoke the method 45 | * @param message to use as a parameter to the component method invocation 46 | * 47 | * @throws NullPointerException if any of the provided parameters 48 | * are {@code null} 49 | */ 50 | void onMessage(@NotNull U component, @NotNull Object message); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/HasSuperInterface.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | public interface HasSuperInterface { 4 | 5 | /** 6 | * Returns the super interface that is common for all messages 7 | * to be handled by this object. 8 | * 9 | * @return the super interface that is common for all messages 10 | * to be handled by this object 11 | */ 12 | Class superInterface(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/IntObjMap.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import com.koloboke.compile.KolobokeMap; 4 | import com.koloboke.function.IntObjConsumer; 5 | import net.openhft.chronicle.core.io.IORuntimeException; 6 | import net.openhft.chronicle.wire.AbstractMarshallable; 7 | import net.openhft.chronicle.wire.WireIn; 8 | import net.openhft.chronicle.wire.WireOut; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | /** 12 | * A long to Object Map. 13 | */ 14 | @KolobokeMap 15 | public abstract class IntObjMap extends AbstractMarshallable { 16 | Class vClass; 17 | 18 | public static IntObjMap withExpectedSize(Class vClass, int expectedSize) { 19 | if (expectedSize < 8) 20 | return new SmallIntObjMap<>(expectedSize + 1); 21 | KolobokeIntObjMap map = new KolobokeIntObjMap<>(expectedSize); 22 | map.vClass = vClass; 23 | return map; 24 | } 25 | 26 | public abstract void justPut(int key, V value); 27 | 28 | public abstract V get(int key); 29 | 30 | public abstract int size(); 31 | 32 | public abstract boolean containsKey(int key); 33 | 34 | public abstract void clear(); 35 | 36 | public abstract void forEach(IntObjConsumer longObjConsumer); 37 | 38 | @Override 39 | public void readMarshallable(@NotNull WireIn wire) throws IORuntimeException { 40 | clear(); 41 | while (wire.isNotEmptyAfterPadding()) { 42 | int k = (int) wire.readEventNumber(); 43 | V v = wire.getValueIn().object(vClass); 44 | justPut(k, v); 45 | } 46 | } 47 | 48 | @Override 49 | public void writeMarshallable(@NotNull WireOut wire) { 50 | forEach((k, v) -> wire.writeEventId(k).object(vClass, v)); 51 | } 52 | 53 | public abstract String toString(); 54 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/KeyPair.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.bytes.BytesStore; 5 | import net.openhft.chronicle.salt.Ed25519; 6 | import net.openhft.chronicle.wire.AbstractMarshallable; 7 | 8 | // TODO Deduplicate with Ed25519.KeyPair 9 | public class KeyPair extends AbstractMarshallable { 10 | public final BytesStore publicKey = Bytes.allocateDirect(Ed25519.PUBLIC_KEY_LENGTH); 11 | public final BytesStore secretKey = Bytes.allocateDirect(Ed25519.SECRET_KEY_LENGTH); 12 | 13 | /** 14 | * Generate a new public and secret key pair using a random seed. 15 | */ 16 | public KeyPair() { 17 | Ed25519.generatePublicAndSecretKey((Bytes) publicKey, (Bytes) secretKey); 18 | } 19 | 20 | /** 21 | * Only use this for testing 22 | * 23 | * @param id to use as a private seed 24 | */ 25 | public KeyPair(long id) { 26 | Bytes privateKey = Bytes.allocateDirect(Ed25519.PRIVATE_KEY_LENGTH); 27 | privateKey.zeroOut(0, Ed25519.PRIVATE_KEY_LENGTH); 28 | privateKey.writeLong(Ed25519.PRIVATE_KEY_LENGTH - (long) Long.BYTES, id); 29 | privateKey.writeSkip(Ed25519.PRIVATE_KEY_LENGTH); 30 | Ed25519.privateToPublicAndSecret((Bytes) publicKey, (Bytes) secretKey, privateKey); 31 | privateKey.releaseLast(); 32 | } 33 | 34 | @Deprecated(/* to be removed in x.22 */) 35 | public KeyPair(char ch) { 36 | Bytes privateKey = Bytes.allocateDirect(Ed25519.PRIVATE_KEY_LENGTH); 37 | while (privateKey.writeRemaining() > 0) 38 | privateKey.append(ch); 39 | Ed25519.privateToPublicAndSecret((Bytes) publicKey, (Bytes) secretKey, privateKey); 40 | privateKey.releaseLast(); 41 | } 42 | 43 | public long address() { 44 | return DecentredUtil.toAddress(publicKey); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/LetterBase32.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import java.util.Arrays; 4 | 5 | public enum LetterBase32 { 6 | ; // none 7 | 8 | private static final int MASK_5 = 0x1F; 9 | private static final ThreadLocal SB_TL = ThreadLocal.withInitial(StringBuilder::new); 10 | private static final byte[] VALUES = new byte[128]; 11 | private static final char[] ENCODE = ".abcdefghijklmnopqrstuvwxyz23467".toCharArray(); 12 | 13 | static { 14 | Arrays.fill(VALUES, (byte) -1); 15 | for (int i = 0; i < ENCODE.length; i++) { 16 | VALUES[ENCODE[i]] = (byte) i; 17 | VALUES[Character.toUpperCase(ENCODE[i])] = (byte) i; 18 | } 19 | VALUES['@'] = 0; 20 | VALUES['0'] = VALUES['o']; 21 | VALUES['1'] = VALUES['l']; 22 | VALUES['5'] = VALUES['S']; 23 | VALUES['8'] = VALUES['B']; 24 | VALUES['9'] = VALUES['q']; 25 | } 26 | 27 | public static long decode(CharSequence text) { 28 | long value = 0; 29 | for (int i = 0; i < text.length(); i++) { 30 | byte code = VALUES[text.charAt(i)]; 31 | if (code < 0) 32 | throw new IllegalArgumentException("Cannot decode " + text); 33 | value = (value << 5) + (code & 0xff); 34 | } 35 | return value; 36 | } 37 | 38 | public static String encode(long value) { 39 | StringBuilder sb = SB_TL.get(); 40 | sb.setLength(0); 41 | encode(sb, value); 42 | return sb.toString(); 43 | } 44 | 45 | public static void encode(StringBuilder sb, long value) { 46 | int start = sb.length(); 47 | do { 48 | sb.append(ENCODE[(int) (value & MASK_5)]); 49 | value >>>= 5; 50 | } while (value != 0); 51 | int end = sb.length() - 1; 52 | while (start < end) { 53 | char t = sb.charAt(start); 54 | sb.setCharAt(start, sb.charAt(end)); 55 | sb.setCharAt(end, t); 56 | start++; 57 | end--; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/LongDoubleMap.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import com.koloboke.compile.KolobokeMap; 4 | import net.openhft.chronicle.wire.AbstractMarshallable; 5 | 6 | @KolobokeMap 7 | public abstract class LongDoubleMap extends AbstractMarshallable { 8 | public static LongDoubleMap withExpectedSize(int expectedSize) { 9 | return new KolobokeLongDoubleMap(expectedSize); 10 | } 11 | 12 | public abstract void justPut(long key, double value); 13 | 14 | public abstract double getOrDefault(long key, double defau1t); 15 | 16 | public abstract String toString(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/LongLongMap.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import com.koloboke.collect.set.LongSet; 4 | import com.koloboke.compile.KolobokeMap; 5 | import com.koloboke.function.LongLongConsumer; 6 | import net.openhft.chronicle.core.io.IORuntimeException; 7 | import net.openhft.chronicle.wire.AbstractMarshallable; 8 | import net.openhft.chronicle.wire.WireIn; 9 | import net.openhft.chronicle.wire.WireOut; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | import javax.annotation.Nonnull; 13 | 14 | /** 15 | * A long to Object Map. 16 | */ 17 | @KolobokeMap 18 | public abstract class LongLongMap extends AbstractMarshallable { 19 | 20 | private LongLongConsumer put; 21 | 22 | public static LongLongMap withExpectedSize(int expectedSize) { 23 | return new KolobokeLongLongMap(expectedSize); 24 | } 25 | 26 | public abstract void justPut(long key, long value); 27 | 28 | public abstract long get(long key); 29 | 30 | public abstract long getOrDefault(long key, long defau1t); 31 | 32 | public abstract int size(); 33 | 34 | public abstract boolean containsKey(long key); 35 | 36 | public abstract void clear(); 37 | 38 | public abstract void forEach(@Nonnull LongLongConsumer var1); 39 | 40 | public void putAll(LongLongMap map) { 41 | if (put == null) put = this::justPut; 42 | map.forEach(put); 43 | } 44 | 45 | @Override 46 | public void readMarshallable(@NotNull WireIn wire) throws IORuntimeException { 47 | clear(); 48 | while (wire.isNotEmptyAfterPadding()) { 49 | long k = wire.readEventNumber(); 50 | long v = wire.getValueIn().int64(); 51 | justPut(k, v); 52 | } 53 | } 54 | 55 | @Override 56 | public void writeMarshallable(@NotNull WireOut wire) { 57 | forEach((k, v) -> wire.writeEvent(Long.class, k).int64(v)); 58 | } 59 | 60 | public abstract LongSet keySet(); 61 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/LongObjMap.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import com.koloboke.compile.KolobokeMap; 4 | import com.koloboke.function.LongObjConsumer; 5 | import net.openhft.chronicle.core.io.IORuntimeException; 6 | import net.openhft.chronicle.wire.AbstractMarshallable; 7 | import net.openhft.chronicle.wire.WireIn; 8 | import net.openhft.chronicle.wire.WireOut; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | import java.util.function.LongFunction; 12 | 13 | /** 14 | * A long to Object Map. 15 | */ 16 | @KolobokeMap 17 | public abstract class LongObjMap extends AbstractMarshallable { 18 | Class vClass; 19 | 20 | public static LongObjMap withExpectedSize(Class vClass, int expectedSize) { 21 | KolobokeLongObjMap kolobokeXCLLongObjMap = new KolobokeLongObjMap<>(expectedSize); 22 | kolobokeXCLLongObjMap.vClass = vClass; 23 | return kolobokeXCLLongObjMap; 24 | } 25 | 26 | public abstract void justPut(long key, V value); 27 | 28 | public abstract V get(long key); 29 | 30 | public abstract int size(); 31 | 32 | public abstract boolean containsKey(long key); 33 | 34 | public abstract void clear(); 35 | 36 | public abstract void forEach(LongObjConsumer longObjConsumer); 37 | 38 | @Override 39 | public void readMarshallable(@NotNull WireIn wire) throws IORuntimeException { 40 | clear(); 41 | while (wire.isNotEmptyAfterPadding()) { 42 | long k = wire.readEventNumber(); 43 | V v = wire.getValueIn().object(vClass); 44 | justPut(k, v); 45 | } 46 | } 47 | 48 | @Override 49 | public void writeMarshallable(@NotNull WireOut wire) { 50 | forEach((k, v) -> wire.writeEvent(Long.class, k).object(vClass, v)); 51 | } 52 | 53 | public abstract V computeIfAbsent(long key, LongFunction supplier); 54 | 55 | public abstract boolean justRemove(long key); 56 | } -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/LongU32Writer.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import com.koloboke.function.LongLongConsumer; 4 | import net.openhft.chronicle.bytes.BytesOut; 5 | 6 | /** 7 | * Class used for writing a long and and an unsigned int to a ByteOut. 8 | * 9 | */ 10 | public final class LongU32Writer implements LongLongConsumer { 11 | 12 | private final BytesOut bytes; 13 | 14 | public LongU32Writer(BytesOut bytes) { 15 | this.bytes = bytes; 16 | } 17 | 18 | /** 19 | * Writes the provided parameters into an internal {@link #bytes}. 20 | * 21 | * @param k long to write 22 | * @param v unsigned int to write 23 | */ 24 | @Override 25 | public void accept(long k, long v) { 26 | bytes.writeLong(k).writeUnsignedInt(v); 27 | } 28 | 29 | /* *//** 30 | * Sets the ByteOut to use for writing when subsequent calls 31 | * to the {@link #accept(long, long)} method are made. 32 | *

33 | * This method must be invoked before the {@link #accept(long, long)} method. 34 | * 35 | * @param bytes to use for writing 36 | * @throws NullPointerException if the provided {@code bytes} 37 | * is {@code null} 38 | * 39 | *//* 40 | public void bytes(BytesOut bytes) { 41 | this.bytes = requireNonNull(bytes); 42 | }*/ 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/OffsetIntConverter.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.wire.IntConverter; 4 | 5 | import java.time.ZoneOffset; 6 | 7 | public class OffsetIntConverter implements IntConverter { 8 | @Override 9 | public int parse(CharSequence text) { 10 | ZoneOffset zo = ZoneOffset.of(text.toString()); 11 | return zo.getTotalSeconds(); 12 | } 13 | 14 | @Override 15 | public void append(StringBuilder text, int value) { 16 | text.append(ZoneOffset.ofTotalSeconds(value)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/PublicKeyRegistry.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.wire.LongConversion; 5 | 6 | public interface PublicKeyRegistry { 7 | void register(@LongConversion(AddressLongConverter.class) long address, BytesStore publicKey); 8 | 9 | Boolean verify(@LongConversion(AddressLongConverter.class) long address, BytesStore sigAndMsg); 10 | 11 | boolean internal(); 12 | 13 | PublicKeyRegistry internal(boolean internal); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/SmallIntObjMap.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import com.koloboke.function.IntObjConsumer; 4 | 5 | public class SmallIntObjMap extends IntObjMap { 6 | private final int[] keys; 7 | private final V[] values; 8 | private int size = 0; 9 | 10 | public SmallIntObjMap(int capacity) { 11 | keys = new int[capacity]; 12 | values = (V[]) new Object[capacity]; 13 | } 14 | 15 | @Override 16 | public void justPut(int key, V value) { 17 | for (int i = 0; i < size; i++) { 18 | if (keys[i] == key) { 19 | values[i] = value; 20 | return; 21 | } 22 | } 23 | keys[size] = key; 24 | values[size] = value; 25 | size++; 26 | } 27 | 28 | @Override 29 | public V get(int key) { 30 | for (int i = 0; i < size; i++) { 31 | if (keys[i] == key) { 32 | return values[i]; 33 | } 34 | } 35 | return null; 36 | } 37 | 38 | @Override 39 | public int size() { 40 | return size; 41 | } 42 | 43 | @Override 44 | public boolean containsKey(int key) { 45 | for (int i = 0; i < size; i++) { 46 | if (keys[i] == key) { 47 | return true; 48 | } 49 | } 50 | return false; 51 | } 52 | 53 | @Override 54 | public void clear() { 55 | size = 0; 56 | } 57 | 58 | @Override 59 | public void forEach(IntObjConsumer longObjConsumer) { 60 | for (int i = 0; i < size; i++) { 61 | longObjConsumer.accept(keys[i], values[i]); 62 | } 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | StringBuilder sb = new StringBuilder(); 68 | sb.append("{ "); 69 | for (int i = 0; i < size; i++) { 70 | if (i > 0) 71 | sb.append(", "); 72 | sb.append(keys[i]).append("=").append(values[i]); 73 | } 74 | sb.append("}"); 75 | return sb.toString(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/net/openhft/chronicle/decentred/util/VanillaPublicKeyRegistry.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.salt.Ed25519; 5 | 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | public class VanillaPublicKeyRegistry implements PublicKeyRegistry { 10 | private final Map publicKeyMap = new ConcurrentHashMap<>(); 11 | private boolean internal; 12 | 13 | @Override 14 | public void register(long address, BytesStore publicKey) { 15 | publicKeyMap.put(address, publicKey.copy()); 16 | } 17 | 18 | @Override 19 | public Boolean verify(long address, BytesStore sigAndMsg) { 20 | if (internal) 21 | return true; 22 | BytesStore publicKey = publicKeyMap.get(address); 23 | if (publicKey == null) return null; 24 | return Ed25519.verify(sigAndMsg, publicKey); 25 | } 26 | 27 | @Override 28 | public boolean internal() { 29 | return internal; 30 | } 31 | 32 | @Override 33 | public PublicKeyRegistry internal(boolean internal) { 34 | this.internal = internal; 35 | return this; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/EndOfRoundBlockEventTester.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto; 2 | 3 | import net.openhft.chronicle.decentred.api.ConnectionStatusListener; 4 | import net.openhft.chronicle.decentred.api.MessageRouter; 5 | import net.openhft.chronicle.decentred.api.Verifier; 6 | 7 | interface EndOfRoundBlockEventTester extends Verifier, MessageRouter, ConnectionStatusListener { 8 | } 9 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/TransactionBlockGossipEventTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.core.time.UniqueMicroTimeProvider; 5 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockGossipEvent; 6 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 7 | import net.openhft.chronicle.decentred.util.KeyPair; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | final class TransactionBlockGossipEventTest { 13 | 14 | @Test 15 | void marshalUnmarshal() { 16 | final KeyPair kp = new KeyPair(1); 17 | 18 | final Bytes bytes = Bytes.allocateElasticDirect(1000); 19 | 20 | final TransactionBlockGossipEvent expected = new TransactionBlockGossipEvent() 21 | .messageType(0xFFF1) 22 | .protocol(17) 23 | .timestampUS(UniqueMicroTimeProvider.INSTANCE.currentTimeMicros()) 24 | //.blockNumber(42) 25 | .chainAddress(43); 26 | 27 | expected.addressToBlockNumberMap().justPut(+1, 1); 28 | expected.addressToBlockNumberMap().justPut(Long.MAX_VALUE, 2); 29 | expected.addressToBlockNumberMap().justPut(Long.MIN_VALUE, 3); 30 | expected.addressToBlockNumberMap().justPut(~0, 4); 31 | expected.sign(kp.secretKey); 32 | 33 | System.out.println("expected = " + expected); 34 | System.out.println(expected.toHexString()); 35 | 36 | expected.writeMarshallable(bytes); 37 | 38 | //bytes.readPosition(0); 39 | TransactionBlockGossipEvent actual = new TransactionBlockGossipEvent(); 40 | actual.readMarshallable(bytes); 41 | 42 | final String actualString = actual.toString(); 43 | 44 | String expectedString = expected.toString(); 45 | assertEquals(expectedString, actualString); 46 | 47 | AbstractFundamentalDtoTest.assertContains(actualString, " addressToBlockNumberMap: {\n" + 48 | " a: 1,\n" + 49 | " g777777777777: 2,\n" + 50 | " h............: 3,\n" + 51 | " o777777777777: 4\n" + 52 | " }"); 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/address/CreateAddressEventFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.address; 2 | 3 | import net.openhft.chronicle.decentred.dto.address.CreateAddressEvent; 4 | import net.openhft.chronicle.decentred.dto.address.CreateAddressRequest; 5 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 6 | 7 | import java.util.Map; 8 | import java.util.function.Consumer; 9 | import java.util.stream.Stream; 10 | 11 | import static org.junit.jupiter.api.Assertions.assertEquals; 12 | 13 | final class CreateAddressEventFundamentalTest extends AbstractFundamentalDtoTest { 14 | 15 | private final CreateAddressRequest createAddressRequest = createChild(CreateAddressRequest.class); 16 | 17 | CreateAddressEventFundamentalTest() { 18 | super(CreateAddressEvent.class); 19 | } 20 | 21 | @Override 22 | protected void initializeSpecifics(CreateAddressEvent message) { 23 | message.createAddressRequest(createAddressRequest); 24 | } 25 | 26 | @Override 27 | protected void assertInitializedSpecifics(CreateAddressEvent message) { 28 | assertEquals(createAddressRequest, message.createAddressRequest()); 29 | } 30 | 31 | @Override 32 | protected void assertInitializedToString(String s) { 33 | assertContains(s, "createAddressRequest"); 34 | } 35 | 36 | @Override 37 | protected Stream>> forbiddenAfterSign() { 38 | return Stream.of( 39 | entry("createAddressRequest", m -> m.createAddressRequest(createAddressRequest)) 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/address/CreateAddressRequestFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.address; 2 | 3 | import net.openhft.chronicle.decentred.dto.address.CreateAddressRequest; 4 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 5 | 6 | import java.util.Map; 7 | import java.util.function.Consumer; 8 | import java.util.stream.Stream; 9 | 10 | final class CreateAddressRequestFundamentalTest extends AbstractFundamentalDtoTest { 11 | 12 | CreateAddressRequestFundamentalTest() { 13 | super(CreateAddressRequest.class); 14 | } 15 | 16 | @Override 17 | protected void initializeSpecifics(CreateAddressRequest message) {} 18 | 19 | @Override 20 | protected void assertInitializedSpecifics(CreateAddressRequest message) {} 21 | 22 | @Override 23 | protected void assertInitializedToString(String s) {} 24 | 25 | @Override 26 | protected Stream>> forbiddenAfterSign() { 27 | return Stream.empty(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/address/InvalidationEventFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.address; 2 | 3 | import net.openhft.chronicle.decentred.dto.address.InvalidationEvent; 4 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 5 | 6 | import java.util.Map; 7 | import java.util.function.Consumer; 8 | import java.util.stream.Stream; 9 | 10 | final class InvalidationEventFundamentalTest extends AbstractFundamentalDtoTest { 11 | 12 | InvalidationEventFundamentalTest() { 13 | super(InvalidationEvent.class); 14 | } 15 | 16 | @Override 17 | protected void initializeSpecifics(InvalidationEvent message) {} 18 | 19 | @Override 20 | protected void assertInitializedSpecifics(InvalidationEvent message) {} 21 | 22 | @Override 23 | protected void assertInitializedToString(String s) {} 24 | 25 | @Override 26 | protected Stream>> forbiddenAfterSign() { 27 | return Stream.empty(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/chainevent/EndOfRoundBlockEventFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.chainevent; 2 | 3 | import net.openhft.chronicle.decentred.dto.blockevent.EndOfRoundBlockEvent; 4 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 5 | import net.openhft.chronicle.decentred.util.DecentredUtil; 6 | import net.openhft.chronicle.decentred.util.LongLongMap; 7 | 8 | import java.util.Map; 9 | import java.util.function.Consumer; 10 | import java.util.stream.Stream; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | final class EndOfRoundBlockEventFundamentalTest extends AbstractFundamentalDtoTest { 15 | 16 | private static final long CHAIN_ADDRESS = 23424; 17 | private static final int WEEK_NUMBER = 87; 18 | private static final long BLOCK_NUMBER = 2322L; 19 | 20 | private static final long ADDRESS0 = 2325353244323L; 21 | private static final long ADDRESS1 = ADDRESS0 + (1L << 32); 22 | 23 | private static final long BLOCK0 = 927634241L; 24 | private static final long BLOCK1 = 294572682L; 25 | 26 | EndOfRoundBlockEventFundamentalTest() { 27 | super(EndOfRoundBlockEvent.class); 28 | } 29 | 30 | @Override 31 | protected void initializeSpecifics(EndOfRoundBlockEvent message) { 32 | message.chainAddress(CHAIN_ADDRESS); 33 | final LongLongMap map = message.addressToBlockNumberMap(); 34 | map.justPut(ADDRESS0, BLOCK0); 35 | map.justPut(ADDRESS1, BLOCK1); 36 | } 37 | 38 | @Override 39 | protected void assertInitializedSpecifics(EndOfRoundBlockEvent message) { 40 | assertEquals(CHAIN_ADDRESS, message.chainAddress()); 41 | } 42 | 43 | @Override 44 | protected void assertInitializedToString(String s) { 45 | assertContains(s, "chainAddress: " + DecentredUtil.toAddressString(CHAIN_ADDRESS)); 46 | assertContains(s, "addressToBlockNumberMap"); 47 | assertContains(s, DecentredUtil.toAddressString(ADDRESS0) + ": " + BLOCK0); 48 | assertContains(s, DecentredUtil.toAddressString(ADDRESS1) + ": " + BLOCK1); 49 | } 50 | 51 | @Override 52 | protected Stream>> forbiddenAfterSign() { 53 | return Stream.of( 54 | entry("chainAddress", m -> m.chainAddress(1)) 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/chainevent/TransactionBlockGossipEventFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.chainevent; 2 | 3 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockGossipEvent; 4 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 5 | import net.openhft.chronicle.decentred.util.DecentredUtil; 6 | import net.openhft.chronicle.decentred.util.LongLongMap; 7 | 8 | import java.util.Map; 9 | import java.util.function.Consumer; 10 | import java.util.stream.Stream; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | final class TransactionBlockGossipEventFundamentalTest extends AbstractFundamentalDtoTest { 15 | 16 | private static final long CHAIN_ADDRESS = 23424; 17 | 18 | private static final long ADDRESS0 = 2325353244323L; 19 | private static final long ADDRESS1 = ADDRESS0 + (1L << 32); 20 | 21 | private static final long BLOCK0 = 927634241L; 22 | private static final long BLOCK1 = 294572682L; 23 | 24 | TransactionBlockGossipEventFundamentalTest() { 25 | super(TransactionBlockGossipEvent.class); 26 | } 27 | 28 | @Override 29 | protected void initializeSpecifics(TransactionBlockGossipEvent message) { 30 | message.chainAddress(CHAIN_ADDRESS); 31 | final LongLongMap map = message.addressToBlockNumberMap(); 32 | map.justPut(ADDRESS0, BLOCK0); 33 | map.justPut(ADDRESS1, BLOCK1); 34 | } 35 | 36 | @Override 37 | protected void assertInitializedSpecifics(TransactionBlockGossipEvent message) { 38 | assertEquals(CHAIN_ADDRESS, message.chainAddress()); 39 | } 40 | 41 | @Override 42 | protected void assertInitializedToString(String s) { 43 | System.out.println(s); 44 | assertContains(s, "chainAddress: " + DecentredUtil.toAddressString(CHAIN_ADDRESS)); 45 | assertContains(s, "addressToBlockNumberMap"); 46 | assertContains(s, DecentredUtil.toAddressString(ADDRESS0) + ": " + BLOCK0); 47 | assertContains(s, DecentredUtil.toAddressString(ADDRESS1) + ": " + BLOCK1); 48 | } 49 | 50 | @Override 51 | protected Stream>> forbiddenAfterSign() { 52 | return Stream.of( 53 | entry("chainAddress", m -> m.chainAddress(1)) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/chainevent/TransactionBlockVoteEventFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.chainevent; 2 | 3 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockGossipEvent; 4 | import net.openhft.chronicle.decentred.dto.blockevent.TransactionBlockVoteEvent; 5 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 6 | 7 | import java.util.Map; 8 | import java.util.function.Consumer; 9 | import java.util.stream.Stream; 10 | 11 | import static org.junit.jupiter.api.Assertions.assertEquals; 12 | 13 | final class TransactionBlockVoteEventFundamentalTest extends AbstractFundamentalDtoTest { 14 | 15 | private final TransactionBlockGossipEvent transactionBlockGossipEvent = createChild(TransactionBlockGossipEvent.class, TransactionBlockGossipEvent::addressToBlockNumberMap, 37246L); 16 | 17 | TransactionBlockVoteEventFundamentalTest() { 18 | super(TransactionBlockVoteEvent.class); 19 | } 20 | 21 | @Override 22 | protected void initializeSpecifics(TransactionBlockVoteEvent message) { 23 | message.gossipEvent(transactionBlockGossipEvent); 24 | } 25 | 26 | @Override 27 | protected void assertInitializedSpecifics(TransactionBlockVoteEvent message) { 28 | assertEquals(transactionBlockGossipEvent, message.gossipEvent()); 29 | } 30 | 31 | @Override 32 | protected void assertInitializedToString(String s) { 33 | assertContains(s, "gossipEvent"); 34 | } 35 | 36 | @Override 37 | protected Stream>> forbiddenAfterSign() { 38 | return Stream.of( 39 | entry("gosipEvent", m -> m.gossipEvent(null)) 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/chainlifecycle/AssignDelegatesRequestFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.chainlifecycle; 2 | 3 | import net.openhft.chronicle.bytes.BytesStore; 4 | import net.openhft.chronicle.decentred.dto.chainlifecycle.AssignDelegatesRequest; 5 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 6 | import net.openhft.chronicle.decentred.util.KeyPair; 7 | 8 | import java.util.Arrays; 9 | import java.util.Collections; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.function.Consumer; 13 | import java.util.stream.Stream; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | 17 | final class AssignDelegatesRequestFundamentalTest extends AbstractFundamentalDtoTest { 18 | 19 | private static final KeyPair KP0 = new KeyPair(3834323423423L); 20 | private static final KeyPair KP1 = new KeyPair(-2348723834423L); 21 | 22 | private static final List DELEGATES = Arrays.asList( 23 | KP0.publicKey, 24 | KP1.publicKey 25 | ); 26 | 27 | AssignDelegatesRequestFundamentalTest() { 28 | super(AssignDelegatesRequest.class); 29 | } 30 | 31 | @Override 32 | protected void initializeSpecifics(AssignDelegatesRequest message) { 33 | message.delegates(DELEGATES); 34 | } 35 | 36 | @Override 37 | protected void assertInitializedSpecifics(AssignDelegatesRequest message) { 38 | assertEquals(DELEGATES, message.delegates()); 39 | } 40 | 41 | @Override 42 | protected void assertInitializedToString(String s) { 43 | assertContains(s, "!!binary hhlyUOyBenQovuHM04/Gj9kfCo0YVvpuUjlPIoJ11rs="); 44 | assertContains(s, "!!binary T/3gMgGySnXASPfIwAeW0xsNU3Qo3yL24BYs2fHIIPs="); 45 | } 46 | 47 | @Override 48 | protected Stream>> forbiddenAfterSign() { 49 | return Stream.of( 50 | entry("reason", m -> m.delegates(Collections.emptyList())) 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/chainlifecycle/CreateChainRequestFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.chainlifecycle; 2 | 3 | import net.openhft.chronicle.decentred.dto.chainlifecycle.CreateChainRequest; 4 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 5 | 6 | import java.util.Map; 7 | import java.util.function.Consumer; 8 | import java.util.stream.Stream; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | final class CreateChainRequestFundamentalTest extends AbstractFundamentalDtoTest { 13 | 14 | private static final int CYCLE_OFFSET = 2; 15 | private static final int ROUNDS_PER_DAY = 24; 16 | 17 | CreateChainRequestFundamentalTest() { 18 | super(CreateChainRequest.class); 19 | } 20 | 21 | @Override 22 | protected void initializeSpecifics(CreateChainRequest message) { 23 | message.cycleOffset(CYCLE_OFFSET); 24 | message.roundsPerDay(ROUNDS_PER_DAY); 25 | } 26 | 27 | @Override 28 | protected void assertInitializedSpecifics(CreateChainRequest message) { 29 | assertEquals(CYCLE_OFFSET, message.cycleOffset()); 30 | assertEquals(ROUNDS_PER_DAY, message.roundsPerDay()); 31 | } 32 | 33 | @Override 34 | protected void assertInitializedToString(String s) { 35 | assertContains(s, "cycleOffset: +00:00:02"); 36 | assertContains(s, "roundsPerDay: 24"); 37 | } 38 | 39 | @Override 40 | protected Stream>> forbiddenAfterSign() { 41 | return Stream.of( 42 | entry("cycleOffset", m -> m.cycleOffset(1)), 43 | entry("roundsPerDay", m -> m.roundsPerDay(1)) 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/chainlifecycle/CreateTokenRequestFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.chainlifecycle; 2 | 3 | import net.openhft.chronicle.decentred.dto.chainlifecycle.CreateTokenRequest; 4 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 5 | 6 | import java.util.Map; 7 | import java.util.function.Consumer; 8 | import java.util.stream.Stream; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | public final class CreateTokenRequestFundamentalTest extends AbstractFundamentalDtoTest { 13 | 14 | private static final int SYMBOL = 2; 15 | private static final double AMOUNT = 100.0d; 16 | private static final double GRANULARITY = 1.0d; 17 | 18 | CreateTokenRequestFundamentalTest() { 19 | super(CreateTokenRequest.class); 20 | } 21 | 22 | @Override 23 | protected void initializeSpecifics(CreateTokenRequest message) { 24 | message.symbol(SYMBOL); 25 | message.amount(AMOUNT); 26 | message.granularity(GRANULARITY); 27 | } 28 | 29 | @Override 30 | protected void assertInitializedSpecifics(CreateTokenRequest message) { 31 | assertEquals(SYMBOL, message.symbol()); 32 | assertEquals(AMOUNT, message.amount(), EPSILON); 33 | assertEquals(GRANULARITY, message.granularity(), EPSILON); 34 | } 35 | 36 | @Override 37 | protected void assertInitializedToString(String s) { 38 | assertContains(s, "symbol: " + SYMBOL); 39 | assertContains(s, "amount: " + AMOUNT); 40 | assertContains(s, "granularity: " + GRANULARITY); 41 | } 42 | 43 | @Override 44 | protected Stream>> forbiddenAfterSign() { 45 | return Stream.of( 46 | entry("symbol", m -> m.symbol(1)), 47 | entry("amount", m -> m.amount(1.0)), 48 | entry("granularity", m -> m.granularity(1.0)) 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/dto/fundamental/error/ApplicationErrorResponseFundamentalTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.dto.fundamental.error; 2 | 3 | import net.openhft.chronicle.decentred.api.SystemMessages; 4 | import net.openhft.chronicle.decentred.dto.address.CreateAddressRequest; 5 | import net.openhft.chronicle.decentred.dto.error.ApplicationErrorResponse; 6 | import net.openhft.chronicle.decentred.dto.fundamental.base.AbstractFundamentalDtoTest; 7 | import net.openhft.chronicle.decentred.util.DtoRegistry; 8 | 9 | import java.util.Map; 10 | import java.util.function.Consumer; 11 | import java.util.stream.Stream; 12 | 13 | import static org.junit.jupiter.api.Assertions.assertEquals; 14 | 15 | final class ApplicationErrorResponseFundamentalTest extends AbstractFundamentalDtoTest { 16 | 17 | private static final String REASON = "CreateAddressRequest failed due to some reason"; 18 | private CreateAddressRequest createAddressRequest = createChild(CreateAddressRequest.class); 19 | 20 | ApplicationErrorResponseFundamentalTest() { 21 | super(ApplicationErrorResponse.class); 22 | 23 | } 24 | 25 | private static ApplicationErrorResponse create() { 26 | return new ApplicationErrorResponse() 27 | .dtoParser(DtoRegistry.newRegistry(SystemMessages.class).get()); 28 | } 29 | 30 | @Override 31 | protected void initializeSpecifics(ApplicationErrorResponse message) { 32 | final CreateAddressRequest m = createChild(CreateAddressRequest.class); 33 | 34 | message.init(createAddressRequest, REASON); 35 | } 36 | 37 | @Override 38 | protected void assertInitializedSpecifics(ApplicationErrorResponse message) { 39 | assertEquals(REASON, message.reason()); 40 | assertEquals(createAddressRequest, message.origMessage()); 41 | } 42 | 43 | @Override 44 | protected void assertInitializedToString(String s) { 45 | assertContains(s, REASON); 46 | } 47 | 48 | @Override 49 | protected Stream>> forbiddenAfterSign() { 50 | return Stream.of( 51 | entry("reason", m -> m.reason("A")) 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/internal/util/ShortUtilTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.internal.util; 2 | 3 | import org.junit.jupiter.params.ParameterizedTest; 4 | import org.junit.jupiter.params.provider.ValueSource; 5 | 6 | import static org.junit.jupiter.api.Assertions.*; 7 | 8 | final class ShortUtilTest { 9 | 10 | @ParameterizedTest 11 | @ValueSource(ints = {0, 1, 2, Short.MAX_VALUE, 65535}) 12 | void requireUnsignedShort(int i) { 13 | assertEquals(i, ShortUtil.requireUnsignedShort(i)); 14 | } 15 | 16 | @ParameterizedTest 17 | @ValueSource(ints = {Integer.MIN_VALUE, -1, 65536, Integer.MAX_VALUE}) 18 | void requireUnsignedShortThrows(int i) { 19 | assertThrows(ArithmeticException.class, () -> { 20 | ShortUtil.requireUnsignedShort(i); 21 | }); 22 | } 23 | 24 | @ParameterizedTest 25 | @ValueSource(ints = {1, 2, Short.MAX_VALUE, 65535}) 26 | void requirePositiveUnsignedShort(int i) { 27 | assertEquals(i, ShortUtil.requirePositiveUnsignedShort(i)); 28 | } 29 | 30 | @ParameterizedTest 31 | @ValueSource(ints = {Integer.MIN_VALUE, -1, 0, 65536, Integer.MAX_VALUE}) 32 | void requirePositiveUnsignedShortThrows(int i) { 33 | assertThrows(ArithmeticException.class, () -> { 34 | ShortUtil.requirePositiveUnsignedShort(i); 35 | }); 36 | } 37 | 38 | @ParameterizedTest 39 | @ValueSource(ints = {Short.MIN_VALUE, -1, 0, 1, 2, Short.MAX_VALUE}) 40 | void toShortExact(int i) { 41 | assertEquals(i, ShortUtil.toShortExact(i)); 42 | } 43 | 44 | @ParameterizedTest 45 | @ValueSource(ints = {Short.MIN_VALUE - 1, Short.MAX_VALUE + 1}) 46 | void toShortExactThrows(int i) { 47 | assertThrows(ArithmeticException.class, () -> { 48 | ShortUtil.toShortExact(i); 49 | }); 50 | 51 | } 52 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/remote/net/EchoClientMain.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.net; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.core.Jvm; 5 | 6 | import java.io.IOException; 7 | import java.net.InetSocketAddress; 8 | import java.nio.ByteBuffer; 9 | import java.util.Collections; 10 | import java.util.concurrent.atomic.AtomicInteger; 11 | 12 | class EchoClientMain { 13 | public static void main(String[] args) throws IOException { 14 | AtomicInteger counter = new AtomicInteger(); 15 | TCPClientListener clientListener = (client, bytes) -> { 16 | System.out.println(bytes); 17 | counter.decrementAndGet(); 18 | }; 19 | VanillaTCPClient client = new VanillaTCPClient("echo", 20 | Collections.singletonList(new InetSocketAddress("localhost", EchoServerMain.PORT)), 21 | clientListener); 22 | 23 | Bytes bytes = Bytes.elasticByteBuffer(); 24 | for (int i = 0; i < 100; i++) { 25 | bytes.clear().append("Hello ").append(i); 26 | counter.getAndIncrement(); 27 | client.write(bytes); 28 | } 29 | while (counter.get() > 0) 30 | Jvm.pause(50); 31 | client.close(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/remote/net/EchoServerMain.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.net; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.core.io.AbstractCloseable; 5 | import net.openhft.chronicle.core.io.Closeable; 6 | 7 | import java.io.IOException; 8 | 9 | class EchoServerMain extends AbstractCloseable implements Closeable, TCPServerConnectionListener { 10 | static final int PORT = Integer.getInteger("port", 9090); 11 | 12 | private final VanillaTCPServer server; 13 | 14 | EchoServerMain(String name, int port) throws IOException { 15 | server = new VanillaTCPServer(name, port, this); 16 | } 17 | 18 | public static void main(String... args) throws IOException { 19 | new EchoServerMain("echo", PORT); 20 | } 21 | 22 | @Override 23 | public void onNewConnection(TCPServer server, TCPConnection channel) { 24 | System.out.println("Connected " + channel); 25 | } 26 | 27 | @Override 28 | public void onClosedConnection(TCPServer server, TCPConnection channel) { 29 | System.out.println("... Disconnected " + channel); 30 | } 31 | 32 | public void onMessage(TCPServer server, TCPConnection channel, Bytes bytes) throws IOException { 33 | System.out.println("+ " + bytes); 34 | channel.write(bytes); 35 | } 36 | 37 | @Override 38 | protected void performClose() { 39 | server.close(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/remote/rpc/RPCTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.remote.rpc; 2 | 3 | import net.openhft.chronicle.core.Mocker; 4 | import net.openhft.chronicle.decentred.api.Verifier; 5 | import net.openhft.chronicle.decentred.dto.VerificationEvent; 6 | import net.openhft.chronicle.decentred.server.VanillaVerifyIP; 7 | import net.openhft.chronicle.decentred.util.DtoRegistry; 8 | import net.openhft.chronicle.decentred.util.KeyPair; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import java.io.IOException; 12 | import java.util.concurrent.BlockingQueue; 13 | import java.util.concurrent.LinkedBlockingQueue; 14 | 15 | final class RPCTest { 16 | 17 | @Test 18 | void testVerify() throws IOException, InterruptedException { 19 | KeyPair zero = new KeyPair(0); 20 | KeyPair one = new KeyPair(1); 21 | 22 | DtoRegistry protocol = DtoRegistry.newRegistry(Verifier.class) 23 | .addProtocol(1, Verifier.class); 24 | RPCServer server = new RPCServer<>("test", 25 | 9999, 26 | 9999, 27 | zero.publicKey, 28 | zero.secretKey, 29 | Verifier.class, 30 | protocol, 31 | VanillaVerifyIP::new); 32 | 33 | BlockingQueue queue = new LinkedBlockingQueue<>(); 34 | Verifier verifier = Mocker.queuing(Verifier.class, "", queue); 35 | RPCClient client = new RPCClient<>( 36 | "test", 37 | "localhost", 38 | 9999, 39 | zero.secretKey, 40 | protocol, 41 | verifier, 42 | Verifier.class 43 | ); 44 | 45 | VerificationEvent message = protocol.create(VerificationEvent.class); 46 | message.keyVerified(one.publicKey); 47 | client.write(message); 48 | while (queue.size() < 1) 49 | Thread.sleep(100); 50 | for (String s : queue) { 51 | System.out.println(s); 52 | } 53 | client.close(); 54 | server.close(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/server/GatewayTester.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.core.annotation.UsedViaReflection; 4 | import net.openhft.chronicle.decentred.api.MessageRouter; 5 | import net.openhft.chronicle.decentred.api.MessageToListener; 6 | import net.openhft.chronicle.decentred.api.SystemMessages; 7 | 8 | public interface GatewayTester extends DecentredServer, SystemMessages, MessageRouter, MessageToListener { 9 | @UsedViaReflection 10 | void processOneBlock(); 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/server/TransactionProcessorTester.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.server; 2 | 3 | import net.openhft.chronicle.decentred.api.MessageRouter; 4 | import net.openhft.chronicle.decentred.api.SystemMessages; 5 | 6 | interface TransactionProcessorTester extends MessageRouter, SystemMessages { 7 | } 8 | -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/util/AddressLongConverterTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | 7 | final class AddressLongConverterTest { 8 | 9 | @Test 10 | void parseAppend() { 11 | AddressLongConverter ac = new AddressLongConverter(); 12 | StringBuilder sb = new StringBuilder(); 13 | for (String s : ("abcdefghiklm," + 14 | "ol234s67bq," + 15 | "peter.lawrey," + 16 | "abcdefghik2").split(",")) { 17 | long l = ac.parse(s); 18 | sb.setLength(0); 19 | ac.append(sb, l); 20 | assertEquals(s, sb.toString()); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/util/KeyPairTest.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.util; 2 | 3 | import net.openhft.chronicle.core.pool.ClassAliasPool; 4 | import net.openhft.chronicle.wire.Marshallable; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static org.junit.jupiter.api.Assertions.assertEquals; 8 | 9 | public class KeyPairTest { 10 | static { 11 | ClassAliasPool.CLASS_ALIASES.addAlias(KeyPair.class); 12 | } 13 | 14 | @Test 15 | public void marshallable() { 16 | KeyPair kp = new KeyPair(4); 17 | assertEquals("!KeyPair {\n" + 18 | " publicKey: !!binary GGNLUWY17C7zCtzj1jB/dQ+YsFfAdmvLN+8cof3jggk=,\n" + 19 | " secretKey: !!binary AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAYY0tRZjXsLvMK3OPWMH91D5iwV8B2a8s37xyh/eOCCQ==\n" + 20 | "}\n", kp.toString()); 21 | assertEquals("s.wc7vpqy2yw", DecentredUtil.toAddressString(kp.address())); 22 | KeyPair kp2 = Marshallable.fromString(kp.toString()); 23 | assertEquals(kp.address(), kp2.address()); 24 | assertEquals(kp, kp2); 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/java/net/openhft/chronicle/decentred/verification/VerifyIPTester.java: -------------------------------------------------------------------------------- 1 | package net.openhft.chronicle.decentred.verification; 2 | 3 | import net.openhft.chronicle.decentred.api.ConnectionStatusListener; 4 | import net.openhft.chronicle.decentred.api.MessageRouter; 5 | import net.openhft.chronicle.decentred.api.Verifier; 6 | 7 | interface VerifyIPTester extends Verifier, MessageRouter, ConnectionStatusListener { 8 | } 9 | -------------------------------------------------------------------------------- /src/test/resources/gateway/createAddressRequest/in.yaml: -------------------------------------------------------------------------------- 1 | createAddressRequest: { 2 | timestampUS: 2018-08-25T09:45:04.181818, 3 | address: phccofmpy6ci, 4 | publicKey: !!binary 9M9t8hyt2kEJmL46Fs+si0VigLTMQt9OafgMm3ljIOg= 5 | } 6 | --- 7 | processOneBlock: "" 8 | --- -------------------------------------------------------------------------------- /src/test/resources/gateway/createAddressRequest/out.yaml: -------------------------------------------------------------------------------- 1 | register: [ 2 | g62j3usr3yrr, 3 | !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 4 | ] 5 | subscribe: g62j3usr3yrr 6 | --- 7 | onMessageTo: [ 8 | phccofmpy6ci, 9 | !TransactionBlockEvent { 10 | timestampUS: 1970-01-01T00:00:00, 11 | address: server, 12 | chainAddress: main, 13 | weekNumber: 0, 14 | blockNumber: 0, 15 | transactions: [ 16 | !CreateAddressRequest { timestampUS: 2018-09-03T16:00:00.000001, address: g62j3usr3yrr, publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= } 17 | ] 18 | } 19 | ] 20 | onMessageTo: [ 21 | phccofmpy6ci, 22 | !TransactionBlockGossipEvent { 23 | timestampUS: 1970-01-01T00:00:00, 24 | address: server, 25 | chainAddress: 0.0.0.0:0, 26 | weekNumber: 0, 27 | blockNumber: 1, 28 | addressToBlockNumberMap: { 29 | server: 0 30 | } 31 | } 32 | ] 33 | onMessageTo: [ 34 | phccofmpy6ci, 35 | !TransactionBlockVoteEvent { 36 | timestampUS: 1970-01-01T00:00:00, 37 | address: 0.0.0.0:0, 38 | gossipEvent: { timestampUS: 1970-01-01T00:00:00, address: 0.0.0.0:0, chainAddress: 0.0.0.0:0, weekNumber: 0, blockNumber: 1, addressToBlockNumberMap: { server: 0 } } 39 | } 40 | ] 41 | onMessageTo: [ 42 | phccofmpy6ci, 43 | !EndOfRoundBlockEvent { 44 | timestampUS: 1970-01-01T00:00:00, 45 | address: server, 46 | chainAddress: main, 47 | weekNumber: 0, 48 | blockNumber: 1, 49 | addressToBlockNumberMap: { 50 | server: 0 51 | } 52 | } 53 | ] 54 | createAddressRequest: { 55 | timestampUS: 2018-09-03T16:00:00.000001, 56 | address: g62j3usr3yrr, 57 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 58 | } 59 | --- 60 | -------------------------------------------------------------------------------- /src/test/resources/gateway/createAddressRequest/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/createAddressRequest/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/endOfRoundBlockEvent/in.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/endOfRoundBlockEvent/in.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/endOfRoundBlockEvent/out.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/endOfRoundBlockEvent/out.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/endOfRoundBlockEvent/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/endOfRoundBlockEvent/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/invalidationEvent/in.yaml: -------------------------------------------------------------------------------- 1 | invalidationEvent: { 2 | timestampUS: 2018-08-20T12:53:05.000001, 3 | address: ud6jbceicts2, 4 | publicKey: !!binary TsXED8x8VoxtLgRu7iPaz4aAhfQUtmvee9KRyhDKk+o= 5 | } 6 | --- 7 | processOneBlock: !!null "" 8 | --- -------------------------------------------------------------------------------- /src/test/resources/gateway/invalidationEvent/out.yaml: -------------------------------------------------------------------------------- 1 | to: . 2 | invalidationEvent: { 3 | timestampUS: 2018-09-03T16:00:00.000001, 4 | address: ng62j3usr3yrr, 5 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 6 | } 7 | --- 8 | --- 9 | -------------------------------------------------------------------------------- /src/test/resources/gateway/invalidationEvent/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/invalidationEvent/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockEvent/in.yaml: -------------------------------------------------------------------------------- 1 | createAddressRequest: { 2 | timestampUS: 2018-08-20T12:53:04.075128, 3 | address: phccofmpy6ci, 4 | publicKey: !!binary 9M9t8hyt2kEJmL46Fs+si0VigLTMQt9OafgMm3ljIOg= 5 | } 6 | --- 7 | transactionBlockEvent: { 8 | timestampUS: 2018-08-20T12:53:04.076123, 9 | address: phccofmpy6ci, 10 | chainAddress: main, 11 | weekNumber: 0, 12 | blockNumber: 0, 13 | transactions: [ 14 | !CreateAddressRequest { timestampUS: 2018-08-20T12:53:04.075128, address: phccofmpy6ci, publicKey: !!binary 9M9t8hyt2kEJmL46Fs+si0VigLTMQt9OafgMm3ljIOg= }, 15 | !CreateAddressRequest { timestampUS: 2018-08-20T12:53:04.075256, address: ud6jbceicts2, publicKey: !!binary TsXED8x8VoxtLgRu7iPaz4aAhfQUtmvee9KRyhDKk+o= } 16 | ] 17 | } 18 | --- 19 | processOneBlock: !!null "" 20 | --- -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockEvent/out.yaml: -------------------------------------------------------------------------------- 1 | register: [ 2 | g62j3usr3yrr, 3 | !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 4 | ] 5 | subscribe: g62j3usr3yrr 6 | --- 7 | --- 8 | onMessageTo: [ 9 | phccofmpy6ci, 10 | !TransactionBlockEvent { 11 | timestampUS: 1970-01-01T00:00:00, 12 | address: server, 13 | chainAddress: main, 14 | weekNumber: 0, 15 | blockNumber: 0, 16 | transactions: [ 17 | !CreateAddressRequest { timestampUS: 2018-09-03T16:00:00.000001, address: g62j3usr3yrr, publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= } 18 | ] 19 | } 20 | ] 21 | --- 22 | -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockEvent/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/transactionBlockEvent/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockGossipEvent/in.yaml: -------------------------------------------------------------------------------- 1 | transactionBlockGossipEvent: { 2 | timestampUS: 2018-08-20T12:53:04.076123, 3 | address: phccofmpy6ci, 4 | chainAddress: local, 5 | weekNumber: 0, 6 | blockNumber: 0, 7 | addressToBlockNumberMap: { 8 | yyy: 109, 9 | zzz: 195, 10 | xxx: 123 11 | } 12 | } 13 | --- 14 | processOneBlock: "" 15 | --- -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockGossipEvent/out.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockGossipEvent/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/transactionBlockGossipEvent/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockVoteEvent/in.yaml: -------------------------------------------------------------------------------- 1 | transactionBlockVoteEvent: { 2 | timestampUS: 2018-08-20T12:53:04.761234, 3 | address: phccofmpy6ci, 4 | gossipEvent: { 5 | timestampUS: 2018-08-20T12:53:04.076123, 6 | address: phccofmpy6ci, 7 | chainAddress: local, 8 | weekNumber: 0, 9 | blockNumber: 0, 10 | addressToBlockNumberMap: { 11 | yyy: 109, 12 | zzz: 195, 13 | xxx: 123 14 | } 15 | } 16 | } 17 | --- 18 | processOneBlock: !!null "" 19 | --- -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockVoteEvent/out.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | -------------------------------------------------------------------------------- /src/test/resources/gateway/transactionBlockVoteEvent/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/transactionBlockVoteEvent/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/gateway/verificationEvent/in.yaml: -------------------------------------------------------------------------------- 1 | verificationEvent: { 2 | timestampUS: 2018-08-20T12:53:05.000001, 3 | address: ud6jbceicts2, 4 | publicKey: !!binary TsXED8x8VoxtLgRu7iPaz4aAhfQUtmvee9KRyhDKk+o=, 5 | keyVerified: !!binary O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik= 6 | } 7 | --- 8 | processOneBlock: !!null "" 9 | --- -------------------------------------------------------------------------------- /src/test/resources/gateway/verificationEvent/out.yaml: -------------------------------------------------------------------------------- 1 | to: . 2 | verificationEvent: { 3 | timestampUS: 2018-09-03T16:00:00.000001, 4 | address: ng62j3usr3yrr, 5 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M=, 6 | addressVerified: ., 7 | keyVerified: !!binary O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik= 8 | } 9 | --- 10 | --- 11 | -------------------------------------------------------------------------------- /src/test/resources/gateway/verificationEvent/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/gateway/verificationEvent/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/genesis/one/out.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | to: ng62j3usr3yrr 3 | createAddressEvent: { 4 | timestampUS: 2018-09-03T16:00:00.000002, 5 | address: ng62j3usr3yrr, 6 | createAddressRequest: { 7 | timestampUS: 2018-09-03T16:00:00.000001, 8 | address: ng62j3usr3yrr, 9 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 10 | } 11 | } 12 | --- 13 | --- 14 | --- 15 | to: ng62j3usr3yrr 16 | createAddressEvent: { 17 | timestampUS: 2018-09-03T16:00:00.000005, 18 | address: ng62j3usr3yrr, 19 | createAddressRequest: { 20 | timestampUS: 2018-09-03T16:00:00.000004, 21 | address: ng62j3usr3yrr, 22 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 23 | } 24 | } 25 | --- 26 | to: ng62j3usr3yrr 27 | createAddressEvent: { 28 | timestampUS: 2018-09-03T16:00:00.000007, 29 | address: ng62j3usr3yrr, 30 | createAddressRequest: { 31 | timestampUS: 2018-09-03T16:00:00.000006, 32 | address: ng62j3usr3yrr, 33 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 34 | } 35 | } 36 | --- 37 | to: ng62j3usr3yrr 38 | createAddressEvent: { 39 | timestampUS: 2018-09-03T16:00:00.000009, 40 | address: ng62j3usr3yrr, 41 | createAddressRequest: { 42 | timestampUS: 2018-09-03T16:00:00.000008, 43 | address: ng62j3usr3yrr, 44 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 45 | } 46 | } 47 | --- 48 | to: ng62j3usr3yrr 49 | createAddressEvent: { 50 | timestampUS: 2018-09-03T16:00:00.000011, 51 | address: ng62j3usr3yrr, 52 | createAddressRequest: { 53 | timestampUS: 2018-09-03T16:00:00.00001, 54 | address: ng62j3usr3yrr, 55 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 56 | } 57 | } 58 | --- 59 | to: ng62j3usr3yrr 60 | createAddressEvent: { 61 | timestampUS: 2018-09-03T16:00:00.000013, 62 | address: ng62j3usr3yrr, 63 | createAddressRequest: { 64 | timestampUS: 2018-09-03T16:00:00.000012, 65 | address: ng62j3usr3yrr, 66 | publicKey: !!binary 2sMevKFZ0oP4NB/ZDX+hzZW/XsyrZX95UmYuZ+Vq++M= 67 | } 68 | } 69 | --- 70 | --- 71 | --- -------------------------------------------------------------------------------- /src/test/resources/genesis/one/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/genesis/one/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/genesis/sample/in.yaml: -------------------------------------------------------------------------------- 1 | # genesis block test 2 | createAddressRequest: { 3 | address: g62j3usr3yrr, 4 | publicKey: !!binary === 5 | } 6 | --- 7 | createChainRequest: { 8 | address: g62j3usr3yrr, 9 | cycle: WEEKLY, 10 | epochTime: 2018-0802T09:00:00Z, 11 | roundsPerWeek: 100000 # 1 per 864 ms. 12 | } 13 | --- 14 | createAddressRequest: { 15 | address: a7qdfowowgpqz, 16 | publicKey: !!binary === # + 17 | } 18 | --- 19 | createAddressRequest: { 20 | address: 776f2i2ndahy, 21 | publicKey: !!binary === # 9 22 | } 23 | --- 24 | createAddressRequest: { 25 | address: tlfradjvulwo, 26 | publicKey: !!binary === # k 27 | } 28 | --- 29 | createAddressRequest: { 30 | address: aoi6osdp72yit, # v 31 | publicKey: !!binary === 32 | } 33 | --- 34 | createAddressRequest: { 35 | address: 7y7spxnvmau7, 36 | publicKey: !!binary === # O 37 | } 38 | --- 39 | createTokenRequest: { 40 | address: g62j3usr3yrr, 41 | symbol: WORK, 42 | amount: 500.0, 43 | granularity: 0.01 44 | } 45 | --- 46 | actionFeeRequest: { 47 | address: g62j3usr3yrr, 48 | action: transferRequest, 49 | symbol: WORK, 50 | fixed: 0.1, 51 | faction: 0.001, 52 | consumed: 0.50 53 | } 54 | --- 55 | actionFeeRequest: { 56 | address: g62j3usr3yrr, 57 | action: createTokenRequest, 58 | symbol: WORK, 59 | fixed: 1000000, 60 | faction: 0.01, 61 | consumed: 0.50 62 | } 63 | --- 64 | actionRewardRequest: { 65 | address: g62j3usr3yrr, 66 | action: endOfBlockRecord, 67 | symbol: WORK, 68 | amount: 0.01 69 | } 70 | --- 71 | transferRequest: { 72 | address: g62j3usr3yrr, 73 | toAddress: g62j3usr3yrr, 74 | symbol: WORK, 75 | amount: 500.0, 76 | } 77 | --- 78 | clusterTransferRequest: { 79 | address: g62j3usr3yrr, 80 | toAddress: g62j3usr3yrr, 81 | symbol: WORK@g62j3usr3yrr, 82 | amount: 100.0, 83 | } 84 | --- 85 | delegateAddressRequest: { 86 | address: g62j3usr3yrr, 87 | addresses: [ a7qdfowowgpqz, 776f2i2ndahy, tlfradjvulwo, aoi6osdp72yit, 7y7spxnvmau7 ] 88 | } 89 | --- 90 | invalidateAddressEvent: { 91 | address: g62j3usr3yrr # genesis address 92 | } 93 | --- 94 | 95 | -------------------------------------------------------------------------------- /src/test/resources/genesis/sample/out.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/genesis/sample/out.yaml -------------------------------------------------------------------------------- /src/test/resources/genesis/sample/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/genesis/sample/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/raw/endOfRoundBlockEvent/in.yaml: -------------------------------------------------------------------------------- 1 | endOfRoundBlockEvent: { 2 | timestampUS: 2018-08-20T12:53:04.076123, 3 | address: phccofmpy6ci, 4 | chainAddress: local, 5 | weekNumber: 0, 6 | blockNumber: 0, 7 | addressToBlockNumberMap: { 8 | yyy: 109, 9 | zzz: 195, 10 | xxx: 123 11 | } 12 | } 13 | --- 14 | #processOneBlock: "" 15 | #--- -------------------------------------------------------------------------------- /src/test/resources/raw/endOfRoundBlockEvent/out.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | endOfRoundBlockEvent: { 3 | timestampUS: 2018-08-20T12:53:04.076123, 4 | address: phccofmpy6ci, 5 | chainAddress: local, 6 | addressToBlockNumberMap: { 7 | xxx: 123, 8 | yyy: 109, 9 | zzz: 195 10 | } 11 | } 12 | ... 13 | -------------------------------------------------------------------------------- /src/test/resources/raw/endOfRoundBlockEvent/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/raw/endOfRoundBlockEvent/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/verification/one/in.yaml: -------------------------------------------------------------------------------- 1 | verificationEvent: { 2 | timestampUS: "2018-08-08T08:03:08.231112", 3 | address: ab34booole7la, 4 | publicKey: !!binary GucBAEizPpfnf7Kkqg+RF97BjjNhSDfnHlsm1HgpRsg=, 5 | keyVerified: !!binary riUxYqLVMfa4vTGKp64D8nCrhsDLHui/hgeC+vapDpg= 6 | } 7 | --- 8 | onConnection: !!null "" 9 | --- 10 | -------------------------------------------------------------------------------- /src/test/resources/verification/one/out.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | to: . 3 | --- 4 | -------------------------------------------------------------------------------- /src/test/resources/verification/one/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/verification/one/setup.yaml -------------------------------------------------------------------------------- /src/test/resources/verification/step1/in.yaml: -------------------------------------------------------------------------------- 1 | createAddressRequest: { 2 | timestampUS: 2018-08-08T08:03:08.231112, 3 | address: 26065.bc79, 4 | publicKey: !!binary WQnL2+L1VdG2wfERctkxxmGQlkqrkVQ8ebzRZUmbZn8= 5 | } 6 | --- 7 | createAddressEvent: { 8 | timestampUS: 2018-08-08T08:03:08.231112, 9 | address: 26065.bc79, 10 | createAddressRequest: { 11 | timestampUS: 2018-08-08T08:03:08.231112, 12 | address: 26065.bc79, 13 | publicKey: !!binary WQnL2+L1VdG2wfERctkxxmGQlkqrkVQ8ebzRZUmbZn8= 14 | } 15 | } 16 | --- 17 | verificationEvent: { 18 | timestampUS: 2018-08-08T08:03:08.231112, 19 | address: 26065.bc79, 20 | publicKey: !!binary WQnL2+L1VdG2wfERctkxxmGQlkqrkVQ8ebzRZUmbZn8=, 21 | addressVerified: 54087.781, 22 | keyVerified: !!binary z5iG3FI73ytbQnkGbtxua348mppMFaF0gQdH00f+on8= 23 | } 24 | --- 25 | -------------------------------------------------------------------------------- /src/test/resources/verification/step1/out.yaml: -------------------------------------------------------------------------------- 1 | to: 0.0.0.0:0 2 | verificationEvent: { 3 | timestampUS: 2018-08-08T08:03:08.231112, 4 | address: ab34booole7la, 5 | publicKey: !!binary GucBAEizPpfnf7Kkqg+RF97BjjNhSDfnHlsm1HgpRsg=, 6 | keyVerified: !!binary riUxYqLVMfa4vTGKp64D8nCrhsDLHui/hgeC+vapDpg= 7 | } 8 | --- 9 | to: 0.0.0.0:0 10 | verificationEvent: { 11 | timestampUS: 2018-08-08T08:03:08.231112, 12 | address: ab34booole7la, 13 | publicKey: !!binary GucBAEizPpfnf7Kkqg+RF97BjjNhSDfnHlsm1HgpRsg=, 14 | keyVerified: !!binary riUxYqLVMfa4vTGKp64D8nCrhsDLHui/hgeC+vapDpg= 15 | } 16 | --- -------------------------------------------------------------------------------- /src/test/resources/verification/step1/setup.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Chronicle-Decentred/f27f06e910f0b2954d1368c17a6f90f5bfa0e304/src/test/resources/verification/step1/setup.yaml -------------------------------------------------------------------------------- /system.properties: -------------------------------------------------------------------------------- 1 | # Tracing if resources are closed/released correctly. 2 | jvm.resource.tracing=false 3 | check.thread.safety=false 4 | # for profiling 5 | jvm.safepoint.enabled=false --------------------------------------------------------------------------------