├── .gitignore ├── README.md ├── account └── build.gradle ├── build.gradle ├── common ├── build.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── platon │ │ └── common │ │ ├── AppenderName.java │ │ ├── BasicPbCodec.java │ │ ├── cache │ │ ├── DelayCache.java │ │ └── DelayItem.java │ │ ├── config │ │ ├── ConfigProperties.java │ │ ├── IgnoreLoad.java │ │ ├── NodeConfig.java │ │ └── Validated.java │ │ ├── exceptions │ │ ├── DataDecodingException.java │ │ └── DataEncodingException.java │ │ ├── utils │ │ ├── BIUtil.java │ │ ├── ByteArrayMap.java │ │ ├── ByteArraySet.java │ │ ├── ByteArrayWrapper.java │ │ ├── ByteComparator.java │ │ ├── ByteUtil.java │ │ ├── FileUtil.java │ │ ├── LRUHashMap.java │ │ ├── Numeric.java │ │ ├── RandomUtils.java │ │ ├── SetAdapter.java │ │ ├── SpringContextUtil.java │ │ └── StringEnhance.java │ │ └── wrapper │ │ └── DataWord.java │ └── test │ ├── java │ └── org │ │ └── platon │ │ └── common │ │ ├── BasicPbCodecTest.java │ │ ├── config │ │ └── ConfigTest.java │ │ └── utils │ │ └── ByteComparatorTest.java │ └── resources │ └── test-platon.conf ├── config └── platon.conf ├── consensus └── build.gradle ├── core ├── build.gradle └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── platon │ │ │ ├── Start.java │ │ │ └── core │ │ │ ├── Account.java │ │ │ ├── BlockIdentifier.java │ │ │ ├── BlockSummary.java │ │ │ ├── Blockchain.java │ │ │ ├── BlockchainImpl.java │ │ │ ├── Denomination.java │ │ │ ├── EventDispatchWorker.java │ │ │ ├── ExternalAccount.java │ │ │ ├── ImportResult.java │ │ │ ├── PendingStateIfc.java │ │ │ ├── PendingStateImpl.java │ │ │ ├── PendingTransaction.java │ │ │ ├── Permission.java │ │ │ ├── Repository.java │ │ │ ├── TransactionExecutionSummary.java │ │ │ ├── TransactionInfo.java │ │ │ ├── TrieHash.java │ │ │ ├── Worker.java │ │ │ ├── block │ │ │ ├── Block.java │ │ │ ├── BlockHeader.java │ │ │ ├── BlockInfo.java │ │ │ ├── BlockPool.java │ │ │ └── GenesisBlock.java │ │ │ ├── codec │ │ │ ├── DataWordCodec.java │ │ │ ├── TransactionInfoCodec.java │ │ │ └── TransactionReceiptCodec.java │ │ │ ├── config │ │ │ ├── BlockchainConfig.java │ │ │ ├── BlockchainNetConfig.java │ │ │ ├── CommonConfig.java │ │ │ ├── Constants.java │ │ │ ├── CoreConfig.java │ │ │ ├── DBVersionProcessor.java │ │ │ ├── DefaultConfig.java │ │ │ ├── Initializer.java │ │ │ ├── SystemConfig.java │ │ │ └── net │ │ │ │ └── BaseNetConfig.java │ │ │ ├── consensus │ │ │ ├── BaseConsensus.java │ │ │ ├── BftWorker.java │ │ │ ├── ConsensusManager.java │ │ │ ├── DposFace.java │ │ │ ├── NoProofWorker.java │ │ │ └── PrimaryOrderComparator.java │ │ │ ├── datasource │ │ │ ├── DataSourceArray.java │ │ │ ├── JournalSource.java │ │ │ ├── ObjectDataSource.java │ │ │ ├── Serializers.java │ │ │ ├── SourceCodec.java │ │ │ └── TransactionStore.java │ │ │ ├── db │ │ │ ├── AbstractBlockstore.java │ │ │ ├── BlockStoreIfc.java │ │ │ ├── BlockStoreImpl.java │ │ │ ├── ContractDetails.java │ │ │ ├── DbFlushManager.java │ │ │ ├── HeaderStore.java │ │ │ ├── RepositoryImpl.java │ │ │ ├── RepositoryRoot.java │ │ │ ├── RepositoryWrapper.java │ │ │ └── StateSource.java │ │ │ ├── enums │ │ │ ├── AccountTypeEnum.java │ │ │ └── ExtraInfo.java │ │ │ ├── exception │ │ │ ├── AlreadyKnownException.java │ │ │ ├── AlreadySealedException.java │ │ │ ├── BadIrreversibleBlockException.java │ │ │ ├── ErrorGenesisBlockException.java │ │ │ ├── OperationException.java │ │ │ ├── OutOfEnergonException.java │ │ │ ├── OutOfPermissionException.java │ │ │ ├── PlatonException.java │ │ │ └── UnknownParentException.java │ │ │ ├── facade │ │ │ ├── CmdInterface.java │ │ │ ├── Platon.java │ │ │ ├── PlatonFactory.java │ │ │ ├── PlatonImpl.java │ │ │ └── PlatonServer.java │ │ │ ├── genesis │ │ │ ├── GenesisConfig.java │ │ │ ├── GenesisJson.java │ │ │ └── GenesisLoader.java │ │ │ ├── keystore │ │ │ ├── AccountHolder.java │ │ │ ├── CipherParams.java │ │ │ ├── FileSystemKeystore.java │ │ │ ├── KdfParams.java │ │ │ ├── Keystore.java │ │ │ ├── KeystoreCrypto.java │ │ │ ├── KeystoreFormat.java │ │ │ └── KeystoreItem.java │ │ │ ├── listener │ │ │ ├── CompoplexPlatonListener.java │ │ │ ├── PendingTransactionState.java │ │ │ ├── PlatonListener.java │ │ │ ├── PlatonListenerAdapter.java │ │ │ └── RunnableWrapper.java │ │ │ ├── manager │ │ │ └── InitialManager.java │ │ │ ├── mine │ │ │ ├── BlockProduceManager.java │ │ │ ├── CompositeFuture.java │ │ │ ├── MineTask.java │ │ │ ├── MinerAlgorithmIfc.java │ │ │ ├── MinerListener.java │ │ │ ├── MiningResult.java │ │ │ └── NoMinerAlgorithm.java │ │ │ ├── rpc │ │ │ ├── ProtoRpc.java │ │ │ ├── ProtoRpcImpl.java │ │ │ ├── Response.java │ │ │ ├── model │ │ │ │ └── AccountModel.java │ │ │ ├── servant │ │ │ │ └── AtpGrpcServiceImpl.java │ │ │ └── wallet │ │ │ │ ├── FileSystemWalletStore.java │ │ │ │ └── WalletAddressItem.java │ │ │ ├── transaction │ │ │ ├── Bloom.java │ │ │ ├── ExecuteResult.java │ │ │ ├── LogInfo.java │ │ │ ├── Transaction.java │ │ │ ├── TransactionComparator.java │ │ │ ├── TransactionPool.java │ │ │ ├── TransactionReceipt.java │ │ │ └── util │ │ │ │ ├── ByteUtil.java │ │ │ │ └── HashUtil.java │ │ │ ├── utils │ │ │ ├── CompactEncoder.java │ │ │ ├── DecodeResult.java │ │ │ ├── TransactionSortedSet.java │ │ │ └── Utils.java │ │ │ ├── validator │ │ │ ├── TimelinessValidator.java │ │ │ └── model │ │ │ │ └── ValidateBlock.java │ │ │ └── vm │ │ │ ├── CallCreate.java │ │ │ ├── EnergonCost.java │ │ │ ├── MessageCall.java │ │ │ ├── OpCode.java │ │ │ ├── PrecompiledContracts.java │ │ │ ├── VM.java │ │ │ ├── program │ │ │ ├── InternalTransaction.java │ │ │ ├── Memory.java │ │ │ ├── Program.java │ │ │ ├── ProgramPrecompile.java │ │ │ ├── ProgramResult.java │ │ │ ├── Stack.java │ │ │ ├── Storage.java │ │ │ ├── invoke │ │ │ │ ├── ProgramInvoke.java │ │ │ │ ├── ProgramInvokeFactory.java │ │ │ │ ├── ProgramInvokeFactoryImpl.java │ │ │ │ ├── ProgramInvokeImpl.java │ │ │ │ └── ProgramInvokeMockImpl.java │ │ │ └── listener │ │ │ │ ├── CompositeProgramListener.java │ │ │ │ ├── ProgramListener.java │ │ │ │ ├── ProgramListenerAdaptor.java │ │ │ │ ├── ProgramListenerAware.java │ │ │ │ └── ProgramStorageChangeListener.java │ │ │ └── trace │ │ │ ├── Op.java │ │ │ ├── OpActions.java │ │ │ ├── ProgramTrace.java │ │ │ ├── ProgramTraceListener.java │ │ │ └── Serializers.java │ └── resources │ │ └── config │ │ └── genesis.json │ └── test │ ├── java │ └── org │ │ └── platon │ │ └── core │ │ ├── AccountTest.java │ │ ├── block │ │ ├── BlockHeaderTest.java │ │ ├── BlockPoolTest.java │ │ └── BlockTest.java │ │ ├── config │ │ ├── CoreConfigTest.java │ │ └── DefaultConfigTest.java │ │ ├── db │ │ └── RepositoryTest.java │ │ ├── facade │ │ ├── CmdInterfaceTest.java │ │ └── PlatonFactoryTest.java │ │ ├── genesis │ │ └── GenesisLoaderTest.java │ │ ├── keystore │ │ └── KeystoreTest.java │ │ ├── restucture │ │ └── TransactionSendTest.java │ │ ├── rpc │ │ ├── ProtoRpcTest.java │ │ └── TxTest.java │ │ ├── state │ │ └── StateTest.java │ │ ├── transaction │ │ ├── TransactionPoolTest.java │ │ ├── TransactionReceiptTest.java │ │ └── TransactionTest.java │ │ └── validator │ │ └── TimelinessValidatorTest.java │ └── resources │ └── config │ └── genesis.json ├── crypto ├── build.gradle └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── platon │ │ │ └── crypto │ │ │ ├── Base58.java │ │ │ ├── CheckUtil.java │ │ │ ├── ConcatKDFBytesGenerator.java │ │ │ ├── ECIESCoder.java │ │ │ ├── ECIESEngine.java │ │ │ ├── ECIESPublicKeyEncoder.java │ │ │ ├── ECKey.java │ │ │ ├── HashUtil.java │ │ │ ├── MGF1BytesGeneratorExt.java │ │ │ ├── WalletUtil.java │ │ │ ├── config │ │ │ └── Constants.java │ │ │ ├── domain │ │ │ └── WalletJson.java │ │ │ ├── hash │ │ │ ├── Digest.java │ │ │ ├── DigestEngine.java │ │ │ ├── Keccak256.java │ │ │ ├── Keccak512.java │ │ │ └── KeccakCore.java │ │ │ ├── jce │ │ │ ├── ECKeyAgreement.java │ │ │ ├── ECKeyFactory.java │ │ │ ├── ECKeyPairGenerator.java │ │ │ ├── ECSignatureFactory.java │ │ │ └── NewBouncyCastleProvider.java │ │ │ └── zksnark │ │ │ ├── BN128.java │ │ │ ├── BN128Fp.java │ │ │ ├── BN128Fp2.java │ │ │ ├── BN128G1.java │ │ │ ├── BN128G2.java │ │ │ ├── Field.java │ │ │ ├── Fp.java │ │ │ ├── Fp12.java │ │ │ ├── Fp2.java │ │ │ ├── Fp6.java │ │ │ ├── PairingCheck.java │ │ │ └── Params.java │ └── resources │ │ └── logback.xml │ └── test │ ├── java │ └── org │ │ └── platon │ │ └── crypto │ │ ├── HashUtilTest.java │ │ └── WalletUtilTest.java │ └── resources │ ├── keys │ └── 5f2ae1c60a3038956cf3355960cb211de78bab50 │ └── logback.xml ├── gradle.properties ├── gradlew ├── gradlew.bat ├── p2p ├── build.gradle └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── platon │ │ │ └── p2p │ │ │ ├── EccDecoder.java │ │ │ ├── EccEncoder.java │ │ │ ├── ForwardMessageHook.java │ │ │ ├── MessageHook.java │ │ │ ├── NodeClient.java │ │ │ ├── NodeClientChannelHandler.java │ │ │ ├── NodeClientChannelInitializer.java │ │ │ ├── NodeContext.java │ │ │ ├── NodeServer.java │ │ │ ├── NodeServerChannelHandler.java │ │ │ ├── NodeServerChannelInitializer.java │ │ │ ├── P2pChannelHandler.java │ │ │ ├── attach │ │ │ ├── LinkController.java │ │ │ └── LinkService.java │ │ │ ├── common │ │ │ ├── Bytes.java │ │ │ ├── CodecUtils.java │ │ │ ├── HeaderHelper.java │ │ │ ├── KadPluginConfig.java │ │ │ ├── LmdbConfig.java │ │ │ ├── NodeUtils.java │ │ │ ├── PeerConfig.java │ │ │ ├── PlatonMessageHelper.java │ │ │ ├── ProtoBufHelper.java │ │ │ └── ReDiRConfig.java │ │ │ ├── db │ │ │ ├── DB.java │ │ │ ├── DBException.java │ │ │ ├── DBMemoryImp.java │ │ │ └── LmdbImp.java │ │ │ ├── handler │ │ │ ├── PlatonMessageHandler.java │ │ │ ├── PlatonMessageHandlerContext.java │ │ │ └── PlatonMessageType.java │ │ │ ├── plugins │ │ │ ├── KadRoutingTable.java │ │ │ ├── KadTopologyPlugin.java │ │ │ ├── Plugin.java │ │ │ ├── PluginFactory.java │ │ │ ├── ResourceMap.java │ │ │ ├── RoutableIDComparator.java │ │ │ ├── RoutingTable.java │ │ │ ├── TopologyPlugin.java │ │ │ ├── TopologyPluginFactory.java │ │ │ └── kademlia │ │ │ │ ├── Contact.java │ │ │ │ ├── KademliaBucket.java │ │ │ │ ├── KademliaHelp.java │ │ │ │ ├── KademliaRoutingTable.java │ │ │ │ └── KeyComparator.java │ │ │ ├── pubsub │ │ │ ├── MessageIdCache.java │ │ │ ├── PubSub.java │ │ │ ├── PubSubMessageHook.java │ │ │ ├── PubSubRouter.java │ │ │ ├── PubSubService.java │ │ │ ├── PubSubSessionNotify.java │ │ │ └── TimeCache.java │ │ │ ├── redir │ │ │ ├── KeyAlgorithm.java │ │ │ ├── KeySelector.java │ │ │ ├── KeySelectorFactory.java │ │ │ ├── ReDiR.java │ │ │ ├── ReDiRExecption.java │ │ │ ├── ReDiRForwardMessageHook.java │ │ │ ├── ReDiRMessageHook.java │ │ │ ├── ServiceDiscovery.java │ │ │ ├── ServiceDiscoveryManager.java │ │ │ ├── ServiceDiscoverySubCallback.java │ │ │ ├── ServiceDiscoveryUtil.java │ │ │ └── TurnService.java │ │ │ ├── router │ │ │ ├── MessageRouter.java │ │ │ └── RequestManager.java │ │ │ ├── session │ │ │ ├── ChannelAttribute.java │ │ │ ├── CreateSessionHandler.java │ │ │ ├── Session.java │ │ │ ├── SessionManager.java │ │ │ └── SessionNotify.java │ │ │ └── storage │ │ │ ├── StorageController.java │ │ │ └── StorageService.java │ └── resources │ │ ├── config │ │ ├── node.conf │ │ └── node.properties │ │ └── logback.xml │ └── test │ ├── java │ └── org │ │ └── platon │ │ └── p2p │ │ ├── DelayCacheTest.java │ │ ├── ECKeyTools.java │ │ ├── NodeClientTest.java │ │ ├── TestNodeServer1.java │ │ ├── TestNodeServer2.java │ │ ├── TestSeedServer.java │ │ ├── netty │ │ ├── TimerClient.java │ │ ├── TimerClientHandler.java │ │ ├── TimerServer.java │ │ ├── TimerServerHandler.java │ │ └── platon │ │ │ ├── PlaonClientHandler.java │ │ │ ├── PlatonClient.java │ │ │ ├── PlatonClientChannelInitializer.java │ │ │ ├── PlatonServer.java │ │ │ ├── PlatonServerChannelInitializer.java │ │ │ └── PlatonServerHandler.java │ │ ├── plugins │ │ ├── RoutingTableMock.java │ │ └── TestResourceMap.java │ │ ├── pubsub │ │ ├── PubSubClusterTest.java │ │ ├── PubSubRequestCallback.java │ │ ├── PubSubRouterMock.java │ │ ├── PubSubRouterTest.java │ │ ├── PubSubSubCallbackMock.java │ │ ├── PubsubMock.java │ │ ├── PubsubTest.java │ │ └── TimeCacheTest.java │ │ ├── redir │ │ ├── ReDiRClusterNode.java │ │ ├── ReDiRClusterRequestCallback.java │ │ ├── ReDiRClusterTest.java │ │ ├── ReDiRRequestCallback.java │ │ ├── ServiceDiscoverManagerMock.java │ │ └── ServiceDiscoverManagerTest.java │ │ ├── router │ │ └── MessageRouterMock.java │ │ └── test │ │ └── proto │ │ └── AnyTest.java │ └── resources │ └── config │ ├── node1 │ └── node.conf │ ├── node2 │ └── node.conf │ └── seed │ └── node.conf ├── settings.gradle ├── slice ├── build.gradle └── src │ ├── main │ └── proto │ │ └── org │ │ └── platon │ │ ├── core │ │ ├── account.proto │ │ ├── base.proto │ │ ├── block.proto │ │ ├── blockheader.proto │ │ ├── dataword.proto │ │ ├── indexBlockInfo.proto │ │ ├── message │ │ │ ├── errno.proto │ │ │ ├── request.proto │ │ │ └── response.proto │ │ ├── service │ │ │ └── platon.gprc.proto │ │ ├── transaction.v2.proto │ │ ├── transactionInfo.proto │ │ └── transactionReceipt.v2.proto │ │ └── p2p │ │ ├── attach │ │ └── attach.proto │ │ ├── common │ │ └── common.proto │ │ ├── consensus │ │ └── bftmessage.proto │ │ ├── platonmessage.proto │ │ ├── plugin │ │ └── plugin.proto │ │ ├── pubsub │ │ └── pubsub.proto │ │ ├── redir │ │ └── redir.proto │ │ ├── session │ │ └── session.proto │ │ └── storage │ │ └── storage.proto │ └── test │ └── java │ └── org │ └── platon │ └── slice │ └── grpc │ └── StreamObserverManager.java ├── storage ├── build.gradle └── src │ ├── main │ └── java │ │ └── org.platon.storage │ │ ├── datasource │ │ ├── AbstractCachedSource.java │ │ ├── AbstractChainedSource.java │ │ ├── AsyncFlushable.java │ │ ├── AsyncWriteCache.java │ │ ├── BatchSource.java │ │ ├── BatchSourceWriter.java │ │ ├── CachedSource.java │ │ ├── DbSettings.java │ │ ├── DbSource.java │ │ ├── HashedKeySource.java │ │ ├── MemSizeEstimator.java │ │ ├── MultiCache.java │ │ ├── NoDeleteSource.java │ │ ├── NodeKeyCompositor.java │ │ ├── PrefixLookupSource.java │ │ ├── ReadCache.java │ │ ├── ReadWriteCache.java │ │ ├── SerializerIfc.java │ │ ├── Source.java │ │ ├── SourceChainBox.java │ │ ├── WriteCache.java │ │ ├── XorDataSource.java │ │ ├── inmemory │ │ │ └── HashMapDB.java │ │ ├── leveldb │ │ │ └── LevelDBSource.java │ │ └── rocksdb │ │ │ └── RocksDBSource.java │ │ ├── enums │ │ └── OverlimitStrategyEnum.java │ │ ├── exception │ │ └── OverlimitException.java │ │ ├── trie │ │ ├── SecureTrie.java │ │ ├── Trie.java │ │ ├── TrieImpl.java │ │ ├── TrieKey.java │ │ └── TrieProto.java │ │ └── utils │ │ └── AutoLock.java │ └── test │ ├── java │ └── org │ │ └── platon │ │ └── storage │ │ ├── StorageTest.java │ │ ├── datasource │ │ ├── WriteCacheTest.java │ │ ├── leveldb │ │ │ └── LevelDBSourceTest.java │ │ └── rocksdb │ │ │ └── RocksDBSourceTest.java │ │ └── trie │ │ └── TrieTest.java │ └── resources │ ├── applicationContext.xml │ ├── config │ └── system.properties │ └── logback.xml ├── tests └── build.gradle └── vm └── build.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | gradle 3 | .idea 4 | *.impl 5 | *.iml 6 | *.log 7 | *.bak 8 | *.class 9 | logs/* 10 | build/* 11 | account/build/ 12 | common/build/ 13 | consensus/build/ 14 | core/build/ 15 | core/out/ 16 | crypto/build/ 17 | crypto/out/ 18 | p2p/build/ 19 | slice/build/ 20 | storage/build/ 21 | storage/out/ 22 | out/* 23 | slice/src/main/java/ 24 | slice/src/main/grpc/ 25 | core/db-01/ 26 | core/database/ 27 | slice/src/main/java/ 28 | database/ 29 | testdb/ 30 | 31 | out 32 | core/config 33 | core/blockchain 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to PlatON-Java 2 | 3 | For more information, please visit our [wiki](https://github.com/PlatONnetwork/wiki/wiki). 4 | 5 | # About 6 | 7 | PlatON-Java is a pure-Java implementation of the PlatON protocol. 8 | 9 | # Running PlatON-Java 10 | 11 | ##### Importing project to IntelliJ IDEA: 12 | 13 | ``` 14 | > git clone https://github.com/PlatONnetwork/PlatON-Java.git 15 | > cd PlatON-Java 16 | > ./gradlew.bat build 17 | ``` 18 | 19 | IDEA: 20 | * File -> New -> Project from existing sources… 21 | * Select PlatON-Java/build.gradle 22 | * Dialog “Import Project from gradle”: press “OK” 23 | * After building run `org.platon.Start` . 24 | 25 | 26 | # License 27 | PlatON-Java is released under the [LGPL-V3 license](LICENSE). 28 | -------------------------------------------------------------------------------- /account/build.gradle: -------------------------------------------------------------------------------- 1 | sourceCompatibility = 1.8 2 | 3 | dependencies { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | sourceCompatibility = 1.8 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | 9 | compile project(':slice') 10 | compile "com.google.guava:guava:24.1-jre" 11 | 12 | compile "com.madgag.spongycastle:core:1.58.0.0" // for SHA3 and SECP256K1 13 | compile "com.madgag.spongycastle:prov:1.58.0.0" // for SHA3 and SECP256K1 14 | compile "com.fasterxml.jackson.core:jackson-databind:2.5.1" 15 | compile "com.fasterxml.jackson.core:jackson-annotations:2.5.0" 16 | compile "org.apache.commons:commons-collections4:4.0" 17 | 18 | compile "com.cedarsoftware:java-util:1.8.0" 19 | 20 | testCompile group: 'junit', name: 'junit', version: '4.11' 21 | } 22 | 23 | task createJavaProject << { 24 | sourceSets*.java.srcDirs*.each{ it.mkdirs() } 25 | sourceSets*.resources.srcDirs*.each{ it.mkdirs()} 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/config/IgnoreLoad.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.config; 2 | 3 | public @interface IgnoreLoad { 4 | } 5 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/config/NodeConfig.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.config; 2 | 3 | import com.typesafe.config.Config; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class NodeConfig { 8 | private static Logger logger = LoggerFactory.getLogger(NodeConfig.class); 9 | 10 | private Config config; 11 | 12 | public static NodeConfig getInstance() { 13 | return new NodeConfig(ConfigProperties.getInstance().getConfig().getObject("node").toConfig()); 14 | } 15 | 16 | private NodeConfig(Config config) { 17 | this.config = config; 18 | } 19 | 20 | public String getHost() { 21 | return config.getString("host"); 22 | } 23 | 24 | public String getPublicKey() { 25 | return config.getString("public-key"); 26 | } 27 | 28 | public String getPrivateKey() { 29 | return config.getString("private-key"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/config/Validated.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.config; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Validated { 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/exceptions/DataDecodingException.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.exceptions; 2 | 3 | 4 | public class DataDecodingException extends RuntimeException { 5 | 6 | public DataDecodingException(String message) { 7 | super(message); 8 | } 9 | 10 | public DataDecodingException(String message, Throwable cause) { 11 | super(message, cause); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/exceptions/DataEncodingException.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.exceptions; 2 | 3 | 4 | public class DataEncodingException extends RuntimeException { 5 | 6 | public DataEncodingException(String message) { 7 | super(message); 8 | } 9 | 10 | public DataEncodingException(String message, Throwable cause) { 11 | super(message, cause); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/utils/ByteArrayWrapper.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.utils; 2 | 3 | import java.io.Serializable; 4 | import java.util.Arrays; 5 | 6 | import static org.platon.common.utils.Numeric.toHexString; 7 | 8 | 9 | public class ByteArrayWrapper implements Comparable, Serializable { 10 | 11 | private final byte[] data; 12 | private int hashCode = 0; 13 | 14 | public ByteArrayWrapper(byte[] data) { 15 | if (null == data) { 16 | throw new NullPointerException("data required."); 17 | } 18 | this.data = data; 19 | // hashCode用于比较 20 | this.hashCode = Arrays.hashCode(data); 21 | } 22 | 23 | public boolean equals(Object other) { 24 | if (!(other instanceof ByteArrayWrapper)) { 25 | return false; 26 | } 27 | byte[] otherData = ((ByteArrayWrapper) other).getData(); 28 | return ByteComparator.compareTo( 29 | data, 0, data.length, 30 | otherData, 0, otherData.length) == 0; 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | return hashCode; 36 | } 37 | 38 | @Override 39 | public int compareTo(ByteArrayWrapper o) { 40 | return ByteComparator.compareTo( 41 | data, 0, data.length, 42 | o.getData(), 0, o.getData().length); 43 | } 44 | 45 | public byte[] getData() { 46 | return data; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return toHexString(data); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/utils/ByteComparator.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.utils; 2 | 3 | public final class ByteComparator { 4 | 5 | public static boolean equals(byte[] b1, byte[] b2) { 6 | return b1.length == b2.length && compareTo(b1, 0, b1.length, b2, 0, b2.length) == 0; 7 | } 8 | 9 | public static int compareTo(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { 10 | return lexicographicalComparerJavaImpl().compareTo( 11 | b1, s1, l1, b2, s2, l2); 12 | } 13 | 14 | private interface Comparer { 15 | int compareTo(T buffer1, int offset1, int length1, 16 | T buffer2, int offset2, int length2); 17 | } 18 | 19 | private static Comparer lexicographicalComparerJavaImpl() { 20 | return PureJavaComparer.INSTANCE; 21 | } 22 | 23 | private enum PureJavaComparer implements Comparer { 24 | 25 | INSTANCE; 26 | 27 | @Override 28 | public int compareTo(byte[] buffer1, int offset1, int length1, 29 | byte[] buffer2, int offset2, int length2) { 30 | 31 | if (buffer1 == buffer2 && offset1 == offset2 && length1 == length2) { 32 | return 0; 33 | } 34 | int end1 = offset1 + length1; 35 | int end2 = offset2 + length2; 36 | for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) { 37 | int a = (buffer1[i] & 0xff); 38 | int b = (buffer2[j] & 0xff); 39 | if (a != b) { 40 | return a - b; 41 | } 42 | } 43 | return length1 - length2; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/utils/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.utils; 2 | 3 | import java.util.Random; 4 | 5 | 6 | public class RandomUtils { 7 | 8 | public static byte[] randomBytes(int length) { 9 | byte[] result = new byte[length]; 10 | new Random().nextBytes(result); 11 | return result; 12 | } 13 | 14 | 15 | public static int randomInt(int maxInt) { 16 | int result = 0; 17 | while (result == 0){ 18 | result = (int)(Math.random()*maxInt); 19 | } 20 | return result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/utils/SpringContextUtil.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.utils; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | @Configuration 12 | @ComponentScan(basePackages={"org.platon"}) 13 | public class SpringContextUtil implements ApplicationContextAware { 14 | 15 | private static ApplicationContext applicationContext; 16 | 17 | @Override 18 | public void setApplicationContext(ApplicationContext applicationContext) { 19 | SpringContextUtil.applicationContext = applicationContext; 20 | } 21 | 22 | public static ApplicationContext getApplicationContext() { 23 | return applicationContext; 24 | } 25 | 26 | public static T getBean(String name) throws BeansException { 27 | return (T)applicationContext.getBean(name); 28 | } 29 | 30 | public static T getBean(Class cls) throws BeansException { 31 | return (T)applicationContext.getBean(cls); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/org/platon/common/utils/StringEnhance.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.utils; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author - Jungle 7 | * @version 0.0.1 8 | * @date 2018/9/14 16:49 9 | */ 10 | public class StringEnhance { 11 | 12 | private StringEnhance() { 13 | } 14 | 15 | public static String join(List src, String delimiter) { 16 | return src == null ? null : String.join(delimiter, src.toArray(new String[0])); 17 | } 18 | 19 | public static String capitaliseFirstLetter(String string) { 20 | if (string == null || string.length() == 0) { 21 | return string; 22 | } else { 23 | return string.substring(0, 1).toUpperCase() + string.substring(1); 24 | } 25 | } 26 | 27 | public static String lowercaseFirstLetter(String string) { 28 | if (string == null || string.length() == 0) { 29 | return string; 30 | } else { 31 | return string.substring(0, 1).toLowerCase() + string.substring(1); 32 | } 33 | } 34 | 35 | public static String zeros(int n) { 36 | return repeat('0', n); 37 | } 38 | 39 | public static String repeat(char value, int n) { 40 | return new String(new char[n]).replace("\0", String.valueOf(value)); 41 | } 42 | 43 | public static boolean isEmpty(String s) { 44 | return s == null || s.length() == 0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/test/java/org/platon/common/utils/ByteComparatorTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.common.utils; 2 | 3 | import org.junit.Ignore; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.*; 7 | 8 | @Ignore 9 | public class ByteComparatorTest { 10 | 11 | @Test 12 | public void test01(){ 13 | byte[] arr01 = new byte[]{1, 2, 3, 4}; 14 | byte[] arr02 = new byte[]{1, 2, 3, 4}; 15 | boolean res = ByteComparator.equals(arr01, arr02); 16 | assertEquals(true, res); 17 | } 18 | 19 | @Test 20 | public void test02(){ 21 | byte[] arr01 = new byte[]{1, 2, 3, 4}; 22 | byte[] arr02 = new byte[]{1, 2, 3, 5}; 23 | boolean res = ByteComparator.equals(arr01, arr02); 24 | assertEquals(false, res); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /consensus/build.gradle: -------------------------------------------------------------------------------- 1 | sourceCompatibility = 1.8 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | testCompile group: 'junit', name: 'junit', version: '4.11' 9 | } 10 | -------------------------------------------------------------------------------- /core/build.gradle: -------------------------------------------------------------------------------- 1 | sourceCompatibility = 1.8 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | ext { 8 | junitVersion = '4.11' 9 | } 10 | 11 | dependencies { 12 | compile project(':slice') 13 | compile project(':crypto') 14 | compile project(':storage') 15 | compile project(':p2p') 16 | compile "org.apache.commons:commons-lang3:3.4" 17 | compile "org.apache.commons:commons-collections4:4.0" 18 | compile "com.google.protobuf:protobuf-java:3.5.1" 19 | compile "org.bouncycastle:bcprov-jdk15on:1.59" 20 | compile "org.projectlombok:lombok:1.16.20" 21 | compile "com.fasterxml.jackson.core:jackson-databind:2.5.1" 22 | compile "org.codehaus.jackson:jackson-mapper-asl:1.9.13" 23 | 24 | 25 | testCompile group: 'junit', name: 'junit', version: '4.11' 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/Start.java: -------------------------------------------------------------------------------- 1 | package org.platon; 2 | 3 | import org.platon.core.facade.PlatonFactory; 4 | import org.platon.core.facade.PlatonImpl; 5 | 6 | import java.io.IOException; 7 | import java.net.URISyntaxException; 8 | 9 | public class Start { 10 | 11 | public static void main(String args[]) throws IOException, URISyntaxException { 12 | 13 | PlatonImpl platon = (PlatonImpl) PlatonFactory.createPlaton(); 14 | 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/BlockIdentifier.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.platon.common.utils.Numeric; 5 | import org.platon.core.proto.BlockIdentifierMessage; 6 | 7 | public class BlockIdentifier { 8 | 9 | private byte[] hash; 10 | 11 | private long number; 12 | 13 | public BlockIdentifier(BlockIdentifierMessage pbMessage) { 14 | this.hash = pbMessage.getHash().toByteArray(); 15 | this.number = pbMessage.getNumber(); 16 | } 17 | 18 | public BlockIdentifier(byte[] hash, long number) { 19 | this.hash = hash; 20 | this.number = number; 21 | } 22 | 23 | public byte[] getHash() { 24 | return hash; 25 | } 26 | 27 | public long getNumber() { 28 | return number; 29 | } 30 | 31 | public byte[] getEncoded() { 32 | BlockIdentifierMessage.Builder builder = BlockIdentifierMessage.newBuilder(); 33 | builder.setHash(ByteString.copyFrom(hash)); 34 | builder.setNumber(number); 35 | return builder.build().toByteArray(); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "BlockIdentifier {" + 41 | "hash=" + Numeric.toHexString(hash) + 42 | ", number = " + number + 43 | '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/BlockSummary.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import org.platon.core.block.Block; 4 | import org.platon.core.transaction.TransactionReceipt; 5 | 6 | import java.math.BigInteger; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class BlockSummary { 11 | 12 | private final Block block; 13 | private final Map rewards; 14 | private final List receipts; 15 | private final List txExecutionSummaries; 16 | private BigInteger totalDifficulty = BigInteger.ZERO; 17 | 18 | public BlockSummary(Block block, Map bigIntegerHashMap, 19 | List transactionReceipts, 20 | List txExecutionSummaries) { 21 | 22 | this.receipts = transactionReceipts; 23 | this.rewards = bigIntegerHashMap; 24 | this.block = block; 25 | this.txExecutionSummaries = txExecutionSummaries; 26 | } 27 | 28 | public List getReceipts() { 29 | return receipts; 30 | } 31 | 32 | public List getSummaries() { 33 | return txExecutionSummaries; 34 | } 35 | 36 | 37 | public Map getRewards() { 38 | return rewards; 39 | } 40 | 41 | public void setTotalDifficulty(BigInteger totalDifficulty) { 42 | this.totalDifficulty = totalDifficulty; 43 | } 44 | 45 | public BigInteger getTotalDifficulty() { 46 | return totalDifficulty; 47 | } 48 | 49 | public boolean betterThan(BigInteger oldTotDifficulty) { 50 | return getTotalDifficulty().compareTo(oldTotDifficulty) > 0; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/Blockchain.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import org.platon.core.block.BlockHeader; 4 | import org.platon.core.block.Block; 5 | import org.platon.core.db.BlockStoreIfc; 6 | import org.platon.core.transaction.Transaction; 7 | import org.platon.core.transaction.TransactionReceipt; 8 | 9 | import java.math.BigInteger; 10 | import java.util.Iterator; 11 | import java.util.List; 12 | 13 | public interface Blockchain { 14 | 15 | ImportResult tryToConnect(Block block); 16 | 17 | long getSize(); 18 | 19 | BlockSummary add(Block block); 20 | 21 | void storeBlock(Block block, List receipts); 22 | 23 | Block getBlockByNumber(long blockNumber); 24 | 25 | void setBestBlock(Block block); 26 | 27 | Block getBestBlock(); 28 | 29 | boolean hasParentOnTheChain(Block block); 30 | 31 | void close(); 32 | 33 | // ==================== for difficulty ================ 34 | 35 | void updateTotalDifficulty(Block block); 36 | 37 | BigInteger getTotalDifficulty(); 38 | 39 | void setTotalDifficulty(BigInteger totalDifficulty); 40 | 41 | byte[] getBestBlockHash(); 42 | 43 | List getListOfHashesStartFrom(byte[] hash, int qty); 44 | 45 | List getListOfHashesStartFromBlock(long blockNumber, int qty); 46 | 47 | TransactionInfo getTransactionInfo(byte[] hash); 48 | 49 | Block getBlockByHash(byte[] hash); 50 | 51 | void setExitOn(long exitOn); 52 | 53 | byte[] getMinerCoinbase(); 54 | 55 | boolean isBlockExist(byte[] hash); 56 | 57 | BlockStoreIfc getBlockStore(); 58 | 59 | Block createNewBlock(Block parent, List transactions, List uncles); 60 | 61 | Iterator getIteratorOfHeadersStartFrom(BlockIdentifier identifier, int skip, int limit, boolean reverse) ; 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/Denomination.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import java.math.BigInteger; 4 | 5 | 6 | public enum Denomination { 7 | 8 | WEI(newBigInt(0)), 9 | SZABO(newBigInt(12)), 10 | FINNEY(newBigInt(15)), 11 | ETHER(newBigInt(18)); 12 | 13 | private BigInteger amount; 14 | 15 | private Denomination(BigInteger value) { 16 | this.amount = value; 17 | } 18 | 19 | public BigInteger value() { 20 | return amount; 21 | } 22 | 23 | public long longValue() { 24 | return value().longValue(); 25 | } 26 | 27 | private static BigInteger newBigInt(int value) { 28 | return BigInteger.valueOf(10).pow(value); 29 | } 30 | 31 | public static String toFriendlyString(BigInteger value) { 32 | if (value.compareTo(ETHER.value()) == 1 || value.compareTo(ETHER.value()) == 0) { 33 | return Float.toString(value.divide(ETHER.value()).floatValue()) + " ETHER"; 34 | } 35 | else if(value.compareTo(FINNEY.value()) == 1 || value.compareTo(FINNEY.value()) == 0) { 36 | return Float.toString(value.divide(FINNEY.value()).floatValue()) + " FINNEY"; 37 | } 38 | else if(value.compareTo(SZABO.value()) == 1 || value.compareTo(SZABO.value()) == 0) { 39 | return Float.toString(value.divide(SZABO.value()).floatValue()) + " SZABO"; 40 | } 41 | else 42 | return Float.toString(value.divide(WEI.value()).floatValue()) + " WEI"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/ExternalAccount.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import java.math.BigInteger; 4 | 5 | /** 6 | * ExternalAccount 7 | * 8 | * @author yanze 9 | * @desc external account for platON 10 | * @create 2018-07-26 17:26 11 | **/ 12 | public class ExternalAccount extends Account{ 13 | 14 | /** 15 | * nickName for im 16 | */ 17 | private byte[] nickName; 18 | 19 | /** 20 | * contribution for consensus 21 | */ 22 | BigInteger contribution; 23 | 24 | public ExternalAccount(BigInteger balance, byte[] extraRoot, byte[] binHash, byte[] permissionRoot,byte[] nickName,BigInteger contribution) { 25 | super(balance, extraRoot, binHash, permissionRoot); 26 | this.nickName = nickName; 27 | this.contribution = contribution; 28 | } 29 | 30 | public ExternalAccount(byte[] protoBuf) { 31 | super(protoBuf); 32 | } 33 | 34 | @Override 35 | public byte[] getEncoded() { 36 | return super.getEncoded(); 37 | } 38 | 39 | public byte[] getNickName() { 40 | return nickName; 41 | } 42 | 43 | public BigInteger getContribution() { 44 | return contribution; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/ImportResult.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | public enum ImportResult { 4 | IMPORTED_BEST, 5 | IMPORTED_NOT_BEST, 6 | EXIST, 7 | NO_PARENT, 8 | INVALID_BLOCK, 9 | CONSENSUS_BREAK; 10 | 11 | public boolean isSuccessful() { 12 | return equals(IMPORTED_BEST) || equals(IMPORTED_NOT_BEST); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/PendingStateIfc.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import org.platon.core.block.Block; 4 | import org.platon.core.transaction.Transaction; 5 | import org.platon.core.transaction.TransactionReceipt; 6 | 7 | import java.util.List; 8 | 9 | public interface PendingStateIfc { 10 | 11 | /** 12 | * Adds transactions received from the net to the list of wire transactions
13 | * Triggers an update of pending state 14 | * 15 | * @param transactions txs received from the net 16 | * @return sublist of transactions with NEW_PENDING status 17 | */ 18 | List addPendingTransactions(List transactions); 19 | 20 | /** 21 | * Adds transaction to the list of pending state txs
22 | * For the moment this list is populated with txs sent by our peer only
23 | * Triggers an update of pending state 24 | */ 25 | void addPendingTransaction(Transaction tx); 26 | 27 | /** 28 | * It should be called on each block imported as BEST
29 | * Does several things: 30 | *
    31 | *
  • removes block's txs from pending state and wire lists
  • 32 | *
  • removes outdated wire txs
  • 33 | *
  • updates pending state
  • 34 | *
35 | * 36 | * @param block block imported into blockchain as a BEST one 37 | */ 38 | void processBest(Block block, List receipts); 39 | 40 | /** 41 | * @return pending state repository 42 | */ 43 | Repository getRepository(); 44 | 45 | /** 46 | * @return list of pending transactions 47 | */ 48 | List getPendingTransactions(); 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/TransactionExecutionSummary.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | public class TransactionExecutionSummary { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/TransactionInfo.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import org.platon.core.transaction.Transaction; 4 | import org.platon.core.transaction.TransactionReceipt; 5 | 6 | public class TransactionInfo { 7 | 8 | TransactionReceipt receipt; 9 | byte[] blockHash; 10 | byte[] parentBlockHash; 11 | int index; 12 | 13 | public TransactionInfo(TransactionReceipt receipt, byte[] blockHash, int index) { 14 | this.receipt = receipt; 15 | this.blockHash = blockHash; 16 | this.index = index; 17 | } 18 | 19 | public TransactionInfo(TransactionReceipt receipt) { 20 | this.receipt = receipt; 21 | } 22 | 23 | public void setTransaction(Transaction tx){ 24 | this.receipt.setTransaction(tx); 25 | } 26 | 27 | public TransactionReceipt getReceipt(){ 28 | return receipt; 29 | } 30 | 31 | public byte[] getBlockHash() { return blockHash; } 32 | 33 | public byte[] getParentBlockHash() { 34 | return parentBlockHash; 35 | } 36 | 37 | public void setParentBlockHash(byte[] parentBlockHash) { 38 | this.parentBlockHash = parentBlockHash; 39 | } 40 | 41 | public int getIndex() { return index; } 42 | 43 | public boolean isPending() { 44 | return blockHash == null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/TrieHash.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import org.platon.crypto.HashUtil; 4 | import org.platon.storage.trie.Trie; 5 | import org.platon.storage.trie.TrieImpl; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by alliswell on 2018/8/6. 11 | */ 12 | public class TrieHash { 13 | 14 | /** 15 | * Calculate the rootHash of a list of bytes 16 | * note: this function does NOT save the k-v into DB, just calculate the hash 17 | */ 18 | public static byte[] getTrieRoot(List values) { 19 | Trie trie = new TrieImpl(); 20 | 21 | if (values == null || values.isEmpty()) 22 | return HashUtil.EMPTY_HASH; 23 | 24 | for (int i = 0; i < values.size(); i++) { 25 | trie.put(new byte[] {(byte)((i >> 24) & 0xFF), (byte)((i >> 16) & 0xFF), (byte)((i >> 8) & 0xFF),(byte)(i & 0xFF)}, 26 | values.get(i)); 27 | } 28 | return trie.getRootHash(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/block/GenesisBlock.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.block; 2 | 3 | import org.platon.common.utils.Numeric; 4 | import org.platon.core.genesis.GenesisJson; 5 | import org.platon.core.Repository; 6 | 7 | import java.math.BigInteger; 8 | import java.util.LinkedHashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * GenesisBlock 13 | * 14 | * @author yanze 15 | * @desc genesis block 16 | * @create 2018-07-31 17:52 17 | **/ 18 | public class GenesisBlock extends Block { 19 | 20 | private Map accounts = new LinkedHashMap<>(); 21 | 22 | public GenesisBlock(long timestamp, byte[] author, byte[] coinbase, byte[] parentHash, byte[] bloomLog, long number, BigInteger energonUsed, BigInteger energonCeiling, BigInteger difficulty, byte[] extraData) { 23 | super(timestamp, author, coinbase, parentHash, bloomLog, number, energonUsed, energonCeiling, difficulty, extraData); 24 | } 25 | 26 | public GenesisBlock(byte[] encodeBytes) { 27 | super(encodeBytes); 28 | } 29 | 30 | public Map getAccounts() { 31 | return accounts; 32 | } 33 | 34 | public void setAccounts(Map accounts) { 35 | this.accounts = accounts; 36 | } 37 | 38 | public void resolve(Repository repository) { 39 | for (String addrStr : accounts.keySet()) { 40 | byte[] address = Numeric.hexStringToByteArray(addrStr); 41 | BigInteger balance = new BigInteger(accounts.get(addrStr).balance); 42 | repository.createAccount(address); 43 | repository.addBalance(address, balance); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/codec/DataWordCodec.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.codec; 2 | 3 | import com.google.protobuf.ByteString; 4 | import com.google.protobuf.InvalidProtocolBufferException; 5 | import org.platon.common.wrapper.DataWord; 6 | import org.platon.core.proto.DataWordMessage; 7 | 8 | public final class DataWordCodec { 9 | 10 | public static DataWordMessage encode(DataWord dataWord) { 11 | if (null == dataWord) { 12 | return null; 13 | } 14 | DataWordMessage.Builder dataWordBuilder = DataWordMessage.newBuilder(); 15 | dataWordBuilder.setData(ByteString.copyFrom(dataWord.getData())); 16 | return dataWordBuilder.build(); 17 | } 18 | 19 | public static DataWord decode(DataWordMessage dataWordMessage) { 20 | return decode(dataWordMessage.toByteArray()); 21 | } 22 | 23 | public static DataWord decode(byte[] data) { 24 | try { 25 | DataWordMessage message = DataWordMessage.parseFrom(data); 26 | return DataWord.of(message.getData().toByteArray()); 27 | } catch (InvalidProtocolBufferException e) { 28 | throw new RuntimeException(e); 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/config/BlockchainConfig.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.config; 2 | 3 | import org.platon.common.wrapper.DataWord; 4 | import org.platon.core.vm.EnergonCost; 5 | import org.platon.core.vm.OpCode; 6 | import org.platon.core.vm.program.Program; 7 | 8 | import java.math.BigInteger; 9 | 10 | /** 11 | * BlockchainConfig 12 | * 13 | * @author yanze 14 | * @desc blockchian config of net and chain info 15 | * @create 2018-07-31 17:01 16 | **/ 17 | public interface BlockchainConfig { 18 | 19 | /** 20 | * Get blockchain constants 21 | */ 22 | Constants getConstants(); 23 | 24 | /** 25 | * TODO : getConsensus must rewrite so return maybe not String 26 | * @return 27 | */ 28 | String getConsensus(); 29 | 30 | /** 31 | * max energon on block 32 | * @return 33 | */ 34 | BigInteger getEnergonLimit(); 35 | 36 | /** 37 | * interval of producing block 38 | */ 39 | int getBlockProducingInterval(); 40 | 41 | /** 42 | * EVM operations costs 43 | */ 44 | EnergonCost getEnergonCost(); 45 | 46 | /** 47 | * Calculates available energon to be passed for callee 48 | * Since EIP150 49 | * @param op Opcode 50 | * @param requestedEnergon amount of Energon requested by the program 51 | * @param availableEnergon available Energon 52 | * @throws Program.OutOfEnergonException If passed args doesn't conform to limitations 53 | */ 54 | DataWord getCallEnergon(OpCode op, DataWord requestedEnergon, DataWord availableEnergon) throws Program.OutOfEnergonException; 55 | 56 | /** 57 | * Calculates available energon to be passed for contract constructor 58 | * Since EIP150 59 | */ 60 | DataWord getCreateEnergon(DataWord availableEnergon); 61 | 62 | } 63 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/config/BlockchainNetConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.core.config; 19 | 20 | /** 21 | * Describes a set of configs for a specific blockchain depending on the block number 22 | * E.g. the main Ethereum net has at least FrontierConfig and HomesteadConfig depending on the block 23 | * 24 | * Created by Anton Nashatyrev on 25.02.2016. 25 | */ 26 | public interface BlockchainNetConfig { 27 | 28 | /** 29 | * Get the config for the specific block 30 | */ 31 | BlockchainConfig getConfigForBlock(long blockNumber); 32 | 33 | /** 34 | * Returns the constants common for all the blocks in this blockchain 35 | */ 36 | Constants getCommonConstants(); 37 | } 38 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/config/Constants.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.config; 2 | 3 | /** 4 | * Describes different constants 5 | */ 6 | public class Constants { 7 | 8 | public static final int PERMISSION_TRIE_THRESHOLD = 1024; 9 | 10 | public static final String DATABASE_SOURCE_LEVELDB = "leveldb"; 11 | public static final String DATABASE_SOURCE_ROCKSDB = "rocksdb"; 12 | 13 | public static final int ERROR__1001_UNLOCK_ACCOUNT = 1001; 14 | public static final int ERROR__1002_KEY_NOT_FOUND = 1002; 15 | 16 | /** 17 | * New DELEGATECALL opcode introduced in the Homestead release. Before Homestead this opcode should generate 18 | * exception 19 | */ 20 | public boolean hasDelegateCallOpcode() {return false; } 21 | 22 | /** 23 | * Introduced in the Homestead release 24 | */ 25 | public boolean createEmptyContractOnOOG() { 26 | return true; 27 | } 28 | 29 | public int getMAX_CONTRACT_SZIE() { return Integer.MAX_VALUE; } 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/config/DefaultConfig.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.config; 2 | 3 | import org.platon.common.AppenderName; 4 | import org.platon.core.datasource.TransactionStore; 5 | import org.platon.core.db.BlockStoreIfc; 6 | import org.platon.core.db.BlockStoreImpl; 7 | import org.platon.storage.datasource.Source; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.context.ApplicationContext; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.context.annotation.Import; 15 | 16 | @Configuration 17 | @Import(CommonConfig.class) 18 | public class DefaultConfig { 19 | 20 | private static Logger logger = LoggerFactory.getLogger(AppenderName.APPENDER_PLATIN); 21 | 22 | @Autowired 23 | CommonConfig commonConfig; 24 | 25 | @Autowired 26 | ApplicationContext appCtx; 27 | 28 | public DefaultConfig() { 29 | Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception", e)); 30 | } 31 | 32 | public ApplicationContext getAppCtx(){ 33 | return appCtx; 34 | } 35 | 36 | @Bean 37 | public BlockStoreIfc blockStore(){ 38 | BlockStoreImpl indexedBlockStore = new BlockStoreImpl(); 39 | Source block = commonConfig.cachedDbSource("block"); 40 | Source index = commonConfig.cachedDbSource("index"); 41 | indexedBlockStore.init(index, block); 42 | return indexedBlockStore; 43 | } 44 | 45 | @Bean 46 | public TransactionStore transactionStore() { 47 | return new TransactionStore(commonConfig.cachedDbSource("transactions")); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/config/Initializer.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.config; 2 | 3 | import org.platon.common.AppenderName; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.BeansException; 7 | import org.springframework.beans.factory.config.BeanPostProcessor; 8 | 9 | class Initializer implements BeanPostProcessor { 10 | 11 | private static final Logger logger = LoggerFactory.getLogger(AppenderName.APPENDER_PLATIN); 12 | 13 | private void initConfig(SystemConfig config) { 14 | 15 | logger.info("~> initConfig(SystemConfig config)..."); 16 | 17 | //loading blockchain config 18 | config.getBlockchainConfig(); 19 | 20 | //todo: 测试屏蔽 21 | //loading genesis config 22 | //config.getGenesisBlock(); 23 | } 24 | 25 | @Override 26 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 27 | if (bean instanceof SystemConfig) { 28 | initConfig((SystemConfig) bean); 29 | } 30 | return bean; 31 | } 32 | 33 | @Override 34 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 35 | return bean; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/consensus/DposFace.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.consensus; 2 | 3 | import org.platon.common.utils.ByteUtil; 4 | 5 | import java.util.Vector; 6 | 7 | /** 8 | * dpos related 9 | * 10 | * @author alliswell 11 | * @version 0.0.1 12 | * @date 2018/8/28 13:42 13 | */ 14 | public class DposFace { 15 | 16 | /** 17 | * primary node's address list 18 | */ 19 | private Vector primaryList; 20 | /** 21 | * block number of last consensus cycle 22 | */ 23 | private long lastCycleBlockNum = 0L; 24 | 25 | public DposFace() { 26 | this.primaryList = new Vector<>(); 27 | } 28 | 29 | public long getLastCycleBlockNum() { 30 | return lastCycleBlockNum; 31 | } 32 | 33 | public void setLastCycleBlockNum(long lastCycleBlockNum) { 34 | this.lastCycleBlockNum = lastCycleBlockNum; 35 | } 36 | 37 | /** 38 | * TODO get the current primary node's address list 39 | * 40 | * @return 41 | */ 42 | public Vector getCurrentPrimary() { 43 | return this.primaryList; 44 | } 45 | 46 | public boolean isPrimary(byte[] address) { 47 | return ByteUtil.contains(primaryList, address); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/consensus/NoProofWorker.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.consensus; 2 | 3 | import org.platon.core.block.Block; 4 | import org.platon.core.block.BlockHeader; 5 | import org.platon.core.block.BlockPool; 6 | 7 | /** 8 | * Created by alliswell on 2018/7/25. 9 | */ 10 | public class NoProofWorker extends BaseConsensus { 11 | 12 | public NoProofWorker(BlockPool blockPool) { 13 | super(blockPool); 14 | } 15 | 16 | @Override 17 | public boolean shouldSeal() { 18 | return true; 19 | } 20 | 21 | @Override 22 | public byte[] headHash() { 23 | return new byte[0]; 24 | } 25 | 26 | @Override 27 | public long headNumber() { 28 | return 0; 29 | } 30 | 31 | @Override 32 | public byte[] currentIrbHash() { 33 | return new byte[0]; 34 | } 35 | 36 | @Override 37 | public long currentIrbNumber() { 38 | return 0; 39 | } 40 | 41 | @Override 42 | public byte[] lastIrbHash() { 43 | return new byte[0]; 44 | } 45 | 46 | @Override 47 | public long lastIrbNumber() { 48 | return 0; 49 | } 50 | 51 | @Override 52 | public void generateSeal(BlockHeader header) { 53 | System.out.println("controller submit a block, hash=" + header.getHash()); 54 | } 55 | 56 | @Override 57 | public boolean shouldCommit(byte[] blockHash) { 58 | return true; 59 | } 60 | 61 | @Override 62 | protected void processRawBlock(Block block) { 63 | 64 | } 65 | 66 | @Override 67 | protected void mine() { 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/consensus/PrimaryOrderComparator.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.consensus; 2 | 3 | import java.math.BigInteger; 4 | 5 | /** 6 | * compare primary node's address 7 | * 8 | * @author alliswell 9 | * @version 0.0.1 10 | * @date 2018/8/28 19:56 11 | */ 12 | public class PrimaryOrderComparator implements java.util.Comparator { 13 | 14 | /** 15 | * seed of comparator 16 | */ 17 | private byte[] seed; 18 | 19 | public PrimaryOrderComparator(byte[] seed) { 20 | this.seed = seed; 21 | } 22 | 23 | @Override 24 | public int compare(byte[] n1, byte[] n2) { 25 | BigInteger first = new BigInteger(n1).xor(new BigInteger(seed)); 26 | BigInteger second = new BigInteger(n2).xor(new BigInteger(seed)); 27 | return first.subtract(second).intValue(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/datasource/DataSourceArray.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.datasource; 2 | 3 | import org.platon.common.utils.ByteUtil; 4 | import org.spongycastle.util.encoders.Hex; 5 | 6 | import java.util.AbstractList; 7 | 8 | public class DataSourceArray extends AbstractList { 9 | 10 | private ObjectDataSource src; 11 | private static final byte[] SIZE_KEY = Hex.decode("FFFFFFFFFFFFFFFF"); 12 | private int size = -1; 13 | 14 | public DataSourceArray(ObjectDataSource src) { 15 | this.src = src; 16 | } 17 | 18 | public synchronized boolean flush() { 19 | return src.flush(); 20 | } 21 | 22 | @Override 23 | public synchronized V set(int idx, V value) { 24 | if (idx >= size()) { 25 | setSize(idx + 1); 26 | } 27 | src.put(ByteUtil.intToBytes(idx), value); 28 | return value; 29 | } 30 | 31 | @Override 32 | public synchronized void add(int index, V element) { 33 | set(index, element); 34 | } 35 | 36 | @Override 37 | public synchronized V remove(int index) { 38 | throw new RuntimeException("Not supported yet."); 39 | } 40 | 41 | @Override 42 | public synchronized V get(int idx) { 43 | if (idx < 0 || idx >= size()) throw new IndexOutOfBoundsException(idx + " > " + size); 44 | return src.get(ByteUtil.intToBytes(idx)); 45 | } 46 | 47 | @Override 48 | public synchronized int size() { 49 | if (size < 0) { 50 | byte[] sizeBB = src.getSource().get(SIZE_KEY); 51 | size = sizeBB == null ? 0 : ByteUtil.byteArrayToInt(sizeBB); 52 | } 53 | return size; 54 | } 55 | 56 | private synchronized void setSize(int newSize) { 57 | size = newSize; 58 | src.getSource().put(SIZE_KEY, ByteUtil.intToBytes(newSize)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/datasource/ObjectDataSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.datasource; 2 | 3 | import org.platon.storage.datasource.ReadCache; 4 | import org.platon.storage.datasource.SerializerIfc; 5 | import org.platon.storage.datasource.Source; 6 | import org.platon.storage.datasource.SourceChainBox; 7 | 8 | public class ObjectDataSource extends SourceChainBox { 9 | 10 | private ReadCache cache; 11 | private SourceCodec codec; 12 | private Source byteSource; 13 | 14 | public ObjectDataSource(Source byteSource, 15 | SerializerIfc serializer, 16 | int readCacheEntries) { 17 | super(byteSource); 18 | this.byteSource = byteSource; 19 | add(codec = new SourceCodec<>(byteSource, new Serializers.Identity(), serializer)); 20 | if (readCacheEntries > 0) { 21 | add(cache = new ReadCache.BytesKey<>(codec).withMaxCapacity(readCacheEntries)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/db/AbstractBlockstore.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.db; 2 | 3 | import org.platon.core.block.Block; 4 | 5 | public abstract class AbstractBlockstore implements BlockStoreIfc { 6 | 7 | @Override 8 | public byte[] getBlockHashByNumber(long blockNumber, byte[] branchBlockHash) { 9 | Block branchBlock = getBlockByHash(branchBlockHash); 10 | if (branchBlock.getBlockHeader().getNumber() < blockNumber) { 11 | throw new IllegalArgumentException("Requested block number > branch hash number: " + blockNumber + " < " + branchBlock.getBlockHeader().getNumber()); 12 | } 13 | while(branchBlock.getBlockHeader().getNumber() > blockNumber) { 14 | branchBlock = getBlockByHash(branchBlock.getBlockHeader().getParentHash()); 15 | } 16 | return branchBlock.getBlockHeader().getHash(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/db/BlockStoreIfc.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.db; 2 | 3 | import org.platon.core.block.BlockHeader; 4 | import org.platon.core.block.Block; 5 | 6 | import java.math.BigInteger; 7 | import java.util.List; 8 | 9 | /** 10 | * @author - Jungle 11 | * @date 2018/9/3 14:48 12 | * @version 0.0.1 13 | */ 14 | public interface BlockStoreIfc { 15 | 16 | byte[] getBlockHashByNumber(long blockNumber); 17 | 18 | 19 | byte[] getBlockHashByNumber(long blockNumber, byte[] branchBlockHash); 20 | 21 | Block getChainBlockByNumber(long blockNumber); 22 | 23 | Block getBlockByHash(byte[] hash); 24 | 25 | boolean isBlockExist(byte[] hash); 26 | 27 | List getListHashesEndWith(byte[] hash, long qty); 28 | 29 | List getListHeadersEndWith(byte[] hash, long qty); 30 | 31 | List getListBlocksEndWith(byte[] hash, long qty); 32 | 33 | void saveBlock(Block block, BigInteger totalDifficulty, boolean mainChain); 34 | 35 | BigInteger getTotalDifficultyForHash(byte[] hash); 36 | 37 | BigInteger getTotalDifficulty(); 38 | 39 | Block getBestBlock(); 40 | 41 | long getMaxNumber(); 42 | 43 | void flush(); 44 | 45 | void reBranch(Block forkBlock); 46 | 47 | void load(); 48 | 49 | void close(); 50 | } 51 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/db/ContractDetails.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.db; 2 | 3 | import org.platon.common.wrapper.DataWord; 4 | 5 | import javax.annotation.Nullable; 6 | import java.util.Collection; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author - Jungle 13 | * @date 2018/9/3 14:37 14 | * @version 0.0.1 15 | */ 16 | public interface ContractDetails { 17 | 18 | void put(DataWord key, DataWord value); 19 | 20 | DataWord get(DataWord key); 21 | 22 | byte[] getCode(); 23 | 24 | byte[] getCode(byte[] codeHash); 25 | 26 | void setCode(byte[] code); 27 | 28 | byte[] getStorageHash(); 29 | 30 | void decode(byte[] rlpCode); 31 | 32 | void setDirty(boolean dirty); 33 | 34 | void setDeleted(boolean deleted); 35 | 36 | boolean isDirty(); 37 | 38 | boolean isDeleted(); 39 | 40 | byte[] getEncoded(); 41 | 42 | int getStorageSize(); 43 | 44 | Set getStorageKeys(); 45 | 46 | Map getStorage(@Nullable Collection keys); 47 | 48 | Map getStorage(); 49 | 50 | void setStorage(List storageKeys, List storageValues); 51 | 52 | void setStorage(Map storage); 53 | 54 | byte[] getAddress(); 55 | 56 | void setAddress(byte[] address); 57 | 58 | ContractDetails clone(); 59 | 60 | String toString(); 61 | 62 | void syncStorage(); 63 | 64 | ContractDetails getSnapshotTo(byte[] hash); 65 | } 66 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/enums/AccountTypeEnum.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.enums; 2 | 3 | /** 4 | * AccountTypeEnum 5 | * 6 | * @author yanze 7 | * @desc account type 8 | * @create 2018-07-26 17:36 9 | **/ 10 | public enum AccountTypeEnum { 11 | ACCOUNT_TYPE_EXTERNAL(1,"external account"), 12 | ACCOUNT_TYPE_CONTRACT(2,"contract account"); 13 | 14 | private String name; 15 | private int code; 16 | 17 | private AccountTypeEnum(int code, String name){ 18 | this.name = name; 19 | this.code = code; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | public int getCode() { 31 | return code; 32 | } 33 | 34 | public void setCode(int code) { 35 | this.code = code; 36 | } 37 | 38 | public static String getNameByCodeValue(int code){ 39 | AccountTypeEnum[] allEnums = values(); 40 | for(AccountTypeEnum enableStatus : allEnums){ 41 | if(enableStatus.getCode()==code){ 42 | return enableStatus.getName(); 43 | } 44 | } 45 | return null; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/enums/ExtraInfo.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.enums; 2 | 3 | /** 4 | * Created by alliswell on 2018/8/8. 5 | */ 6 | public enum ExtraInfo { 7 | BLOCKINFO((byte)1), 8 | LOGBLOOM((byte)2), 9 | RCECIPTS((byte)3), 10 | TXPOS((byte)4), 11 | BLOCKHASH((byte)5); 12 | private byte value; 13 | 14 | ExtraInfo(byte value) { 15 | this.value = value; 16 | } 17 | public byte getValue() { 18 | return value; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/AlreadyKnownException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | /** 4 | * Created by alliswell on 2018/7/31. 5 | */ 6 | public class AlreadyKnownException extends RuntimeException { 7 | public AlreadyKnownException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/AlreadySealedException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | /** 4 | * Created by alliswell on 2018/8/2. 5 | */ 6 | public class AlreadySealedException extends RuntimeException { 7 | public AlreadySealedException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/BadIrreversibleBlockException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | /** 4 | * bad irreversible block exception 5 | * 6 | * @author alliswell 7 | * @since 2018/08/13 8 | */ 9 | public class BadIrreversibleBlockException extends RuntimeException { 10 | public BadIrreversibleBlockException(String message){ 11 | super(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/ErrorGenesisBlockException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | /** 4 | * Created by alliswell on 2018/8/10. 5 | */ 6 | public class ErrorGenesisBlockException extends RuntimeException { 7 | public ErrorGenesisBlockException(String message){ 8 | super(message); 9 | } 10 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/OperationException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | public class OperationException extends Exception { 4 | 5 | private int errorCode; 6 | 7 | public OperationException(String message, int errorCode) { 8 | 9 | super(message); 10 | this.errorCode = errorCode; 11 | } 12 | 13 | public OperationException(String message) { 14 | super(message); 15 | } 16 | 17 | public OperationException(String message, Throwable cause) { 18 | super(message, cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/OutOfEnergonException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | /** 4 | * Created by alliswell on 2018/7/26. 5 | */ 6 | public class OutOfEnergonException extends RuntimeException { 7 | public OutOfEnergonException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/OutOfPermissionException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | /** 4 | * Created by alliswell on 2018/8/2. 5 | */ 6 | public class OutOfPermissionException extends RuntimeException { 7 | public OutOfPermissionException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/PlatonException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | 4 | public class PlatonException extends RuntimeException { 5 | 6 | private int errorCode; 7 | 8 | public PlatonException(String message, int errorCode) { 9 | super(message); 10 | this.errorCode = errorCode; 11 | } 12 | 13 | public PlatonException(String message) { 14 | super(message); 15 | } 16 | 17 | public PlatonException(String message, Throwable cause) { 18 | super(message, cause); 19 | } 20 | 21 | public int getErrorCode() { 22 | return errorCode; 23 | } 24 | 25 | public void setErrorCode(int errorCode) { 26 | this.errorCode = errorCode; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/exception/UnknownParentException.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.exception; 2 | 3 | /** 4 | * Created by alliswell on 2018/7/31. 5 | */ 6 | public class UnknownParentException extends RuntimeException { 7 | public UnknownParentException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/facade/Platon.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.facade; 2 | 3 | import org.platon.core.TransactionInfo; 4 | import org.platon.core.listener.PlatonListener; 5 | import org.platon.core.Blockchain; 6 | import org.platon.core.transaction.Transaction; 7 | 8 | import java.util.concurrent.Future; 9 | 10 | /** 11 | * @author - Jungle 12 | * @date 2018/9/13 14:14 13 | * @version 0.0.1 14 | */ 15 | public interface Platon { 16 | 17 | Future submitTransaction(Transaction transaction); 18 | 19 | TransactionInfo getTransactionInfo(byte[] hash); 20 | 21 | Blockchain getBlockchain(); 22 | 23 | void addListener(PlatonListener listener); 24 | 25 | void close(); 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/facade/PlatonFactory.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.facade; 2 | 3 | import org.platon.common.AppenderName; 4 | import org.platon.common.config.ConfigProperties; 5 | import org.platon.core.config.DefaultConfig; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class PlatonFactory { 14 | 15 | private static final Logger logger = LoggerFactory.getLogger(AppenderName.APPENDER_PLATIN); 16 | 17 | public static Platon createPlaton() { 18 | return createPlaton((Class) null); 19 | } 20 | 21 | public static Platon createPlaton(Class userSpringConfig) { 22 | return userSpringConfig == null ? 23 | createPlaton(new Class[] {DefaultConfig.class}) : 24 | createPlaton(DefaultConfig.class, userSpringConfig); 25 | } 26 | 27 | public static Platon createPlaton(ConfigProperties config, Class userSpringConfig) { 28 | return userSpringConfig == null ? 29 | createPlaton(new Class[] {DefaultConfig.class}) : 30 | createPlaton(DefaultConfig.class, userSpringConfig); 31 | } 32 | 33 | public static Platon createPlaton(Class ... springConfigs) { 34 | logger.info("~> Starting Platonj..."); 35 | ApplicationContext context = new AnnotationConfigApplicationContext(springConfigs); 36 | return context.getBean(Platon.class); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/facade/PlatonServer.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.facade; 2 | 3 | import io.grpc.Server; 4 | import io.grpc.ServerBuilder; 5 | import org.platon.core.config.CoreConfig; 6 | import org.platon.core.rpc.servant.AtpGrpcServiceImpl; 7 | 8 | import java.io.IOException; 9 | import java.net.URISyntaxException; 10 | 11 | public class PlatonServer { 12 | 13 | private static Server server; 14 | 15 | public static void main(String args[]) throws IOException, URISyntaxException { 16 | 17 | 18 | 19 | final CoreConfig config = CoreConfig.getInstance(); 20 | 21 | PlatonImpl platon = (PlatonImpl) PlatonFactory.createPlaton(); 22 | 23 | 24 | server = ServerBuilder 25 | .forPort(11001) 26 | .addService(new AtpGrpcServiceImpl()) 27 | 28 | .build().start(); 29 | 30 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 31 | @Override 32 | public void run() { 33 | System.out.println("shutdown..."); 34 | server.shutdown(); 35 | } 36 | })); 37 | 38 | try { 39 | server.awaitTermination(); 40 | } catch (InterruptedException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/keystore/AccountHolder.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.keystore; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | 5 | /** 6 | * Manages real accounts 7 | * 8 | * @author alliswell 9 | * @version 0.0.1 10 | * @date 2018/8/30 18:01 11 | */ 12 | public class AccountHolder { 13 | 14 | @Autowired 15 | private Keystore keystore; 16 | 17 | /** 18 | * beneficiary of mining 19 | */ 20 | private byte[] miner; 21 | 22 | /** 23 | * node's address 24 | */ 25 | private byte[] nodeAddress; 26 | 27 | public String[] accounts() { 28 | return keystore.listStoredKeys(); 29 | } 30 | 31 | public byte[] getMiner() { 32 | if (null == miner || 0 == miner.length) { 33 | miner = accounts()[0].getBytes(); 34 | } 35 | return miner; 36 | } 37 | 38 | public void setMiner(byte[] miner) { 39 | this.miner = miner; 40 | } 41 | 42 | public byte[] getNodeAddress() { 43 | return nodeAddress; 44 | } 45 | 46 | public void setNodeAddress(byte[] nodeAddress) { 47 | this.nodeAddress = nodeAddress; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/keystore/CipherParams.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.keystore; 2 | 3 | public class CipherParams { 4 | 5 | private String iv; 6 | 7 | public CipherParams() { 8 | this(null); 9 | } 10 | 11 | public CipherParams(String iv) { 12 | this.iv = iv; 13 | } 14 | 15 | public String getIv() { 16 | return iv; 17 | } 18 | 19 | public void setIv(String iv) { 20 | this.iv = iv; 21 | } 22 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/keystore/KdfParams.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.keystore; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | public class KdfParams { 6 | 7 | private Integer c; 8 | private Integer dklen; 9 | private String salt; 10 | private Integer n; 11 | private Integer p; 12 | private Integer r; 13 | 14 | public Integer getN() { 15 | return n; 16 | } 17 | 18 | public Integer getR() { 19 | return r; 20 | } 21 | 22 | public void setR(Integer r) { 23 | this.r = r; 24 | } 25 | 26 | public void setN(Integer n) { 27 | this.n = n; 28 | } 29 | 30 | public Integer getP() { 31 | return p; 32 | } 33 | 34 | public void setP(Integer p) { 35 | this.p = p; 36 | } 37 | 38 | @JsonIgnore 39 | public Integer getC() { 40 | return c; 41 | } 42 | 43 | public void setC(Integer c) { 44 | this.c = c; 45 | } 46 | 47 | public Integer getDklen() { 48 | return dklen; 49 | } 50 | 51 | public void setDklen(Integer dklen) { 52 | this.dklen = dklen; 53 | } 54 | 55 | public String getSalt() { 56 | return salt; 57 | } 58 | 59 | public void setSalt(String salt) { 60 | this.salt = salt; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/keystore/Keystore.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.keystore; 2 | 3 | import org.platon.crypto.ECKey; 4 | 5 | public interface Keystore { 6 | 7 | void removeKey(String address); 8 | 9 | void storeKey(ECKey key, String password) throws RuntimeException; 10 | 11 | void storeRawKeystore(String content, String address) throws RuntimeException; 12 | 13 | String[] listStoredKeys(); 14 | 15 | ECKey loadStoredKey(String address, String password) throws RuntimeException; 16 | 17 | boolean hasStoredKey(String address); 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/keystore/KeystoreItem.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.keystore; 2 | 3 | import org.codehaus.jackson.annotate.JsonSetter; 4 | 5 | public class KeystoreItem { 6 | 7 | public KeystoreCrypto crypto; 8 | public String id; 9 | public Integer version; 10 | public String address; 11 | 12 | public String getAddress() { 13 | return address; 14 | } 15 | 16 | public void setAddress(String address) { 17 | this.address = address; 18 | } 19 | 20 | public KeystoreCrypto getCrypto() { 21 | return crypto; 22 | } 23 | 24 | @JsonSetter("crypto") 25 | public void setCrypto(KeystoreCrypto crypto) { 26 | this.crypto = crypto; 27 | } 28 | 29 | @JsonSetter("Crypto") 30 | public void setCryptoOld(KeystoreCrypto crypto) { 31 | this.crypto = crypto; 32 | } 33 | 34 | public String getId() { 35 | return id; 36 | } 37 | 38 | public void setId(String id) { 39 | this.id = id; 40 | } 41 | 42 | public Integer getVersion() { 43 | return version; 44 | } 45 | 46 | public void setVersion(Integer version) { 47 | this.version = version; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/listener/PendingTransactionState.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.listener; 2 | 3 | public enum PendingTransactionState { 4 | 5 | /** 6 | * Transaction may be dropped due to: 7 | * - Invalid transaction (invalid nonce, low gas price, insufficient account funds, 8 | * invalid signature) 9 | * - Timeout (when pending transaction is not included to any block for 10 | * last [transaction.outdated.threshold] blocks 11 | * This is the final state 12 | */ 13 | DROPPED, 14 | 15 | /** 16 | * The same as PENDING when transaction is just arrived 17 | * Next state can be either PENDING or INCLUDED 18 | */ 19 | NEW_PENDING, 20 | 21 | /** 22 | * State when transaction is not included to any blocks (on the main chain), and 23 | * was executed on the last best block. The repository state is reflected in the PendingState 24 | * Next state can be either INCLUDED, DROPPED (due to timeout) 25 | * or again PENDING when a new block (without this transaction) arrives 26 | */ 27 | PENDING, 28 | 29 | /** 30 | * State when the transaction is included to a block. 31 | * This could be the final state, however next state could also be 32 | * PENDING: when a fork became the main chain but doesn't include this tx 33 | * INCLUDED: when a fork became the main chain and tx is included into another 34 | * block from the new main chain 35 | * DROPPED: If switched to a new (long enough) main chain without this Tx 36 | */ 37 | INCLUDED; 38 | 39 | public boolean isPending() { 40 | return this == NEW_PENDING || this == PENDING; 41 | } 42 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/listener/PlatonListenerAdapter.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.listener; 2 | 3 | import org.platon.core.block.Block; 4 | import org.platon.core.BlockSummary; 5 | import org.platon.core.PendingStateIfc; 6 | import org.platon.core.transaction.Transaction; 7 | import org.platon.core.transaction.TransactionReceipt; 8 | 9 | import java.util.List; 10 | 11 | public class PlatonListenerAdapter implements PlatonListener { 12 | 13 | @Override 14 | public void trace(String output) { 15 | 16 | } 17 | 18 | @Override 19 | public void onBlock(BlockSummary blockSummary) { 20 | 21 | } 22 | 23 | @Override 24 | public void onPeerDisconnect(String host, long port) { 25 | 26 | } 27 | 28 | @Override 29 | public void onPendingTransactionsReceived(List transactions) { 30 | 31 | } 32 | 33 | @Override 34 | public void onPendingStateChanged(PendingStateIfc pendingState) { 35 | 36 | } 37 | 38 | @Override 39 | public void onPendingTransactionUpdate(TransactionReceipt txReceipt, PendingTransactionState state, Block block) { 40 | 41 | } 42 | 43 | @Override 44 | public void onNoConnections() { 45 | 46 | } 47 | 48 | @Override 49 | public void onVMTraceCreated(String transactionHash, String trace) { 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/listener/RunnableWrapper.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.listener; 2 | 3 | public abstract class RunnableWrapper implements Runnable { 4 | 5 | private PlatonListener listener; 6 | private String info; 7 | 8 | public RunnableWrapper(PlatonListener listener, String info) { 9 | this.listener = listener; 10 | this.info = info; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return "RunnableWrapper: " + info + " [listener: " + listener.getClass() + "]"; 16 | } 17 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/mine/CompositeFuture.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.mine; 2 | 3 | import com.google.common.util.concurrent.AbstractFuture; 4 | import com.google.common.util.concurrent.ListenableFuture; 5 | import com.google.common.util.concurrent.MoreExecutors; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class CompositeFuture extends AbstractFuture { 11 | 12 | private List> futures = new ArrayList<>(); 13 | 14 | public synchronized void add(final ListenableFuture f) { 15 | 16 | if (isCancelled() || isDone()) return; 17 | 18 | f.addListener(() -> futureCompleted(f), MoreExecutors.directExecutor()); 19 | futures.add(f); 20 | } 21 | 22 | private synchronized void futureCompleted(ListenableFuture f) { 23 | if (isCancelled() || isDone()) return; 24 | if (f.isCancelled()) return; 25 | 26 | try { 27 | cancelOthers(f); 28 | V v = f.get(); 29 | postProcess(v); 30 | set(v); 31 | } catch (Exception e) { 32 | setException(e); 33 | } 34 | } 35 | 36 | /** 37 | * Subclasses my override to perform some task on the calculated 38 | * value before returning it via Future 39 | */ 40 | protected void postProcess(V v) {} 41 | 42 | private void cancelOthers(ListenableFuture besidesThis) { 43 | for (ListenableFuture future : futures) { 44 | if (future != besidesThis) { 45 | try { 46 | future.cancel(true); 47 | } catch (Exception e) { 48 | } 49 | } 50 | } 51 | } 52 | 53 | @Override 54 | protected void interruptTask() { 55 | cancelOthers(null); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/mine/MineTask.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.mine; 2 | 3 | import com.google.common.util.concurrent.ListenableFuture; 4 | import com.google.common.util.concurrent.ListeningExecutorService; 5 | import org.platon.core.block.Block; 6 | 7 | import java.util.concurrent.Callable; 8 | 9 | public class MineTask extends CompositeFuture { 10 | 11 | private Block block; 12 | private int nThreads; 13 | private Callable miner; 14 | private ListeningExecutorService executor; 15 | 16 | public MineTask(Block block, int nThreads, Callable miner, 17 | ListeningExecutorService executor) { 18 | this.block = block; 19 | this.nThreads = nThreads; 20 | this.miner = miner; 21 | this.executor = executor; 22 | } 23 | 24 | public MineTask submit() { 25 | for (int i = 0; i < nThreads; i++) { 26 | ListenableFuture f = executor.submit(miner); 27 | add(f); 28 | } 29 | return this; 30 | } 31 | 32 | @Override 33 | protected void postProcess(MiningResult result) { 34 | 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/mine/MinerAlgorithmIfc.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.mine; 2 | 3 | import com.google.common.util.concurrent.ListenableFuture; 4 | import org.platon.core.block.BlockHeader; 5 | import org.platon.core.block.Block; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * @author - Jungle 11 | * @date 2018/9/5 10:55 12 | * @version 0.0.1 13 | */ 14 | public interface MinerAlgorithmIfc { 15 | 16 | /** 17 | * Starts mining the block. On successful mining the Block is update with necessary nonce and hash. 18 | * @return MiningResult Future object. The mining can be canceled via this Future. The Future is complete 19 | * when the block successfully mined. 20 | */ 21 | ListenableFuture mine(Block block); 22 | 23 | /** 24 | * Validates the Proof of Work for the block 25 | */ 26 | boolean validate(BlockHeader blockHeader); 27 | 28 | /** 29 | * Passes {@link MinerListener}'s to miner 30 | */ 31 | void setListeners(Collection listeners); 32 | 33 | boolean shouldSeal(); 34 | 35 | byte[] headHash(); 36 | 37 | byte[] currentIrbHash(); 38 | 39 | byte[] lastIrbHash(); 40 | 41 | void generateSeal(BlockHeader header); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/mine/MinerListener.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.mine; 2 | 3 | import org.platon.core.block.Block; 4 | 5 | 6 | public interface MinerListener { 7 | 8 | void miningStarted(); 9 | 10 | void miningStopped(); 11 | 12 | void blockMiningStarted(Block block); 13 | 14 | void blockMined(Block block); 15 | 16 | void blockMiningCanceled(Block block); 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/mine/MiningResult.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.mine; 2 | 3 | import org.platon.core.block.Block; 4 | 5 | public class MiningResult { 6 | 7 | public final long nonce; 8 | 9 | public final byte[] digest; 10 | 11 | public final Block block; 12 | 13 | public MiningResult(long nonce, byte[] digest, Block block) { 14 | this.nonce = nonce; 15 | this.digest = digest; 16 | this.block = block; 17 | } 18 | 19 | public long getNonce() { 20 | return nonce; 21 | } 22 | 23 | public byte[] getDigest() { 24 | return digest; 25 | } 26 | 27 | public Block getBlock() { 28 | return block; 29 | } 30 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/rpc/wallet/WalletAddressItem.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.rpc.wallet; 2 | 3 | public class WalletAddressItem { 4 | 5 | public String address; 6 | 7 | public String name; 8 | 9 | public WalletAddressItem(String address, String name) { 10 | this.address = address; 11 | this.name = name; 12 | } 13 | 14 | public String getAddress() { 15 | return address; 16 | } 17 | 18 | public void setAddress(String address) { 19 | this.address = address; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | @Override 31 | public boolean equals(Object o) { 32 | if (this == o) return true; 33 | if (o == null || getClass() != o.getClass()) return false; 34 | 35 | WalletAddressItem that = (WalletAddressItem) o; 36 | 37 | if (getAddress() != null ? !getAddress().equals(that.getAddress()) : that.getAddress() != null) return false; 38 | return getName() != null ? getName().equals(that.getName()) : that.getName() == null; 39 | } 40 | 41 | @Override 42 | public int hashCode() { 43 | int result = getAddress() != null ? getAddress().hashCode() : 0; 44 | result = 31 * result + (getName() != null ? getName().hashCode() : 0); 45 | return result; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/transaction/ExecuteResult.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.transaction; 2 | 3 | import java.math.BigInteger; 4 | 5 | /** transaction execute result 6 | * Created by alliswell on 2018/8/2. 7 | */ 8 | public class ExecuteResult { 9 | private BigInteger energonUsed; 10 | byte[] contractAddress; 11 | byte[] output; 12 | BigInteger energonRefunded; 13 | int depositSize; 14 | BigInteger energonForDeposit; 15 | 16 | public ExecuteResult() { 17 | } 18 | 19 | public void setEnergonUsed(BigInteger energonUsed) { 20 | this.energonUsed = energonUsed; 21 | } 22 | 23 | public void setContractAddress(byte[] contractAddress) { 24 | this.contractAddress = contractAddress; 25 | } 26 | 27 | public void setOutput(byte[] output) { 28 | this.output = output; 29 | } 30 | 31 | public void setEnergonRefunded(BigInteger energonRefunded) { 32 | this.energonRefunded = energonRefunded; 33 | } 34 | 35 | public void setDepositSize(int depositSize) { 36 | this.depositSize = depositSize; 37 | } 38 | 39 | public void setEnergonForDeposit(BigInteger energonForDeposit) { 40 | this.energonForDeposit = energonForDeposit; 41 | } 42 | 43 | public BigInteger getEnergonUsed() { 44 | return energonUsed; 45 | } 46 | 47 | public byte[] getContractAddress() { 48 | return contractAddress; 49 | } 50 | 51 | public byte[] getOutput() { 52 | return output; 53 | } 54 | 55 | public BigInteger getEnergonRefunded() { 56 | return energonRefunded; 57 | } 58 | 59 | public int getDepositSize() { 60 | return depositSize; 61 | } 62 | 63 | public BigInteger getEnergonForDeposit() { 64 | return energonForDeposit; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/transaction/TransactionComparator.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.transaction; 2 | 3 | /** 4 | * Created by alliswell on 2018/7/24. 5 | */ 6 | public class TransactionComparator implements java.util.Comparator { 7 | @Override 8 | public int compare(Transaction t1, Transaction t2) { 9 | return t1.getEnergonPrice().subtract(t2.getEnergonPrice()).intValue(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/transaction/util/HashUtil.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.transaction.util; 2 | 3 | import org.bouncycastle.jcajce.provider.digest.SHA3; 4 | 5 | public class HashUtil { 6 | 7 | public static byte[] EMPTY_ROOT = bcSHA3Digest256(new byte[0]); 8 | // bouncycastle SHA3 9 | public static byte[] bcSHA3Digest256(byte[] value) { 10 | SHA3.DigestSHA3 digestSHA3 = new SHA3.Digest256(); 11 | return digestSHA3.digest(value); 12 | } 13 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/utils/DecodeResult.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.utils; 2 | 3 | import org.spongycastle.util.encoders.Hex; 4 | 5 | import java.io.Serializable; 6 | 7 | @SuppressWarnings("serial") 8 | public class DecodeResult implements Serializable { 9 | 10 | private int pos; 11 | private Object decoded; 12 | 13 | public DecodeResult(int pos, Object decoded) { 14 | this.pos = pos; 15 | this.decoded = decoded; 16 | } 17 | 18 | public int getPos() { 19 | return pos; 20 | } 21 | 22 | public Object getDecoded() { 23 | return decoded; 24 | } 25 | 26 | public String toString() { 27 | return asString(this.decoded); 28 | } 29 | 30 | private String asString(Object decoded) { 31 | if (decoded instanceof String) { 32 | return (String) decoded; 33 | } else if (decoded instanceof byte[]) { 34 | return Hex.toHexString((byte[]) decoded); 35 | } else if (decoded instanceof Object[]) { 36 | String result = ""; 37 | for (Object item : (Object[]) decoded) { 38 | result += asString(item); 39 | } 40 | return result; 41 | } 42 | throw new RuntimeException("Not a valid type. Should not occur"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/utils/TransactionSortedSet.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.utils; 2 | 3 | import org.platon.common.utils.ByteComparator; 4 | import org.platon.core.transaction.Transaction; 5 | 6 | import java.util.TreeSet; 7 | 8 | public class TransactionSortedSet extends TreeSet { 9 | public TransactionSortedSet() { 10 | super((tx1, tx2) -> { 11 | long refBlockNumDiff = tx1.getReferenceBlockNum() - tx2.getReferenceBlockNum(); 12 | if (refBlockNumDiff != 0) { 13 | return refBlockNumDiff > 0 ? 1 : -1; 14 | } 15 | return ByteComparator.compareTo(tx1.getHash(), 0, 32, tx2.getHash(), 0, 32); 16 | }); 17 | } 18 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/vm/CallCreate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.core.vm; 19 | 20 | /** 21 | * @author Roman Mandeleil 22 | * @since 03.07.2014 23 | */ 24 | public class CallCreate { 25 | 26 | final byte[] data; 27 | final byte[] destination; 28 | final byte[] gasLimit; 29 | final byte[] value; 30 | 31 | 32 | public CallCreate(byte[] data, byte[] destination, byte[] gasLimit, byte[] value) { 33 | this.data = data; 34 | this.destination = destination; 35 | this.gasLimit = gasLimit; 36 | this.value = value; 37 | } 38 | 39 | public byte[] getData() { 40 | return data; 41 | } 42 | 43 | public byte[] getDestination() { 44 | return destination; 45 | } 46 | 47 | public byte[] getGasLimit() { 48 | return gasLimit; 49 | } 50 | 51 | public byte[] getValue() { 52 | return value; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/vm/program/invoke/ProgramInvokeFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.core.vm.program.invoke; 19 | 20 | import org.platon.common.wrapper.DataWord; 21 | import org.platon.core.Repository; 22 | import org.platon.core.block.Block; 23 | import org.platon.core.db.BlockStoreIfc; 24 | import org.platon.core.transaction.Transaction; 25 | import org.platon.core.vm.program.Program; 26 | 27 | import java.math.BigInteger; 28 | 29 | /** 30 | * @author Roman Mandeleil 31 | * @since 19.12.2014 32 | */ 33 | public interface ProgramInvokeFactory { 34 | 35 | ProgramInvoke createProgramInvoke(Transaction tx, Block block, 36 | Repository repository, BlockStoreIfc blockStore); 37 | 38 | ProgramInvoke createProgramInvoke(Program program, DataWord toAddress, DataWord callerAddress, 39 | DataWord inValue, DataWord inGas, 40 | BigInteger balanceInt, byte[] dataIn, 41 | Repository repository, BlockStoreIfc blockStore, 42 | boolean staticCall, boolean byTestingSuite); 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/vm/program/listener/ProgramListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.core.vm.program.listener; 19 | 20 | 21 | import org.platon.common.wrapper.DataWord; 22 | 23 | public interface ProgramListener { 24 | 25 | void onMemoryExtend(int delta); 26 | 27 | void onMemoryWrite(int address, byte[] data, int size); 28 | 29 | void onStackPop(); 30 | 31 | void onStackPush(DataWord value); 32 | 33 | void onStackSwap(int from, int to); 34 | 35 | void onStoragePut(DataWord key, DataWord value); 36 | 37 | void onStorageClear(); 38 | } -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/vm/program/listener/ProgramListenerAdaptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.core.vm.program.listener; 19 | 20 | import org.platon.common.wrapper.DataWord; 21 | 22 | public class ProgramListenerAdaptor implements ProgramListener { 23 | 24 | @Override 25 | public void onMemoryExtend(int delta) { 26 | 27 | } 28 | 29 | @Override 30 | public void onMemoryWrite(int address, byte[] data, int size) { 31 | 32 | } 33 | 34 | @Override 35 | public void onStackPop() { 36 | 37 | } 38 | 39 | @Override 40 | public void onStackPush(DataWord value) { 41 | 42 | } 43 | 44 | @Override 45 | public void onStackSwap(int from, int to) { 46 | 47 | } 48 | 49 | @Override 50 | public void onStoragePut(DataWord key, DataWord value) { 51 | 52 | } 53 | 54 | @Override 55 | public void onStorageClear() { 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/vm/program/listener/ProgramListenerAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.core.vm.program.listener; 19 | 20 | public interface ProgramListenerAware { 21 | 22 | void setProgramListener(ProgramListener listener); 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/org/platon/core/vm/program/listener/ProgramStorageChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.core.vm.program.listener; 19 | 20 | import org.platon.common.wrapper.DataWord; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | public class ProgramStorageChangeListener extends ProgramListenerAdaptor { 26 | 27 | private Map diff = new HashMap<>(); 28 | 29 | @Override 30 | public void onStoragePut(DataWord key, DataWord value) { 31 | diff.put(key, value); 32 | } 33 | 34 | @Override 35 | public void onStorageClear() { 36 | // TODO: ... 37 | } 38 | 39 | public Map getDiff() { 40 | return new HashMap<>(diff); 41 | } 42 | 43 | public void merge(Map diff) { 44 | this.diff.putAll(diff); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/resources/config/genesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "consensus": "Noproof", 4 | "energonLimit": "1388" 5 | }, 6 | "accounts": { 7 | "5f2ae1c60a3038956cf3355960cb211de78bab50": { 8 | "balance": "10000000000000000000000" 9 | } 10 | }, 11 | "autor": "5f2ae1c60a3038956cf3355960cb211de78bab50", 12 | "coinbase" : "5f2ae1c60a3038956cf3355960cb211de78bab50", 13 | "timestamp": "1533872936173", 14 | "parentHash": "0000000000000000000000000000000000000000000000000000000000000000", 15 | "energonLimit": "1388" 16 | } -------------------------------------------------------------------------------- /core/src/test/java/org/platon/core/AccountTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.core; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.math.BigInteger; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | public class AccountTest { 11 | 12 | final BigInteger balance = new BigInteger("10000"); 13 | final byte[] storageRoot = "storageRoot".getBytes(); 14 | final byte[] binHash = "binHash".getBytes(); 15 | final byte[] permissionRoot = "permissionRoot".getBytes(); 16 | 17 | @Test 18 | public void getEncoded() { 19 | Account account = this.init(); 20 | Account account1 = new Account(account.getEncoded()); 21 | Assert.assertArrayEquals(account.getStorageRoot(),account1.getStorageRoot()); 22 | } 23 | 24 | @Test 25 | public void addBalance() { 26 | Account account = this.init(); 27 | BigInteger addBalance = new BigInteger("-1"); 28 | account.addBalance(addBalance); 29 | Assert.assertEquals(account.getBalance().toString(),balance.add(addBalance).toString()); 30 | } 31 | 32 | @Test 33 | public void isEmpty() { 34 | Account account = this.init(); 35 | Assert.assertFalse(account.isEmpty()); 36 | } 37 | 38 | @Test 39 | public void untouch() { 40 | Account account = this.init(); 41 | account.untouch(); 42 | Assert.assertFalse(account.isDirty()); 43 | } 44 | 45 | private Account init(){ 46 | return new Account(balance,storageRoot,binHash,permissionRoot); 47 | } 48 | } -------------------------------------------------------------------------------- /core/src/test/java/org/platon/core/config/CoreConfigTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.config; 2 | 3 | import com.typesafe.config.Config; 4 | import com.typesafe.config.ConfigFactory; 5 | import org.junit.Assert; 6 | import org.junit.Ignore; 7 | import org.junit.Test; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | @Ignore 13 | public class CoreConfigTest { 14 | 15 | @Test 16 | public void test01(){ 17 | System.out.println("work.dir:" + System.getProperty("user.dir")); 18 | CoreConfig coreConfig = CoreConfig.getInstance(); 19 | System.out.println("database.dir:" + coreConfig.databaseDir()); 20 | 21 | // tips: for override. 22 | Map override = new HashMap<>(); 23 | override.put("database.dir", "otherdir"); 24 | coreConfig.overrideParams(override); 25 | Assert.assertEquals("otherdir",coreConfig.databaseDir()); 26 | 27 | // tips: 28 | Config cliConf = ConfigFactory.parseString("a={a1=1,a2=2}"); 29 | coreConfig.overrideParams(cliConf); 30 | String a1 = coreConfig.getConfig().getString("a.a1"); 31 | System.out.println(a1); 32 | Assert.assertEquals("1",a1); 33 | } 34 | } -------------------------------------------------------------------------------- /core/src/test/java/org/platon/core/facade/CmdInterfaceTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.facade; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Ignore; 5 | import org.junit.Test; 6 | import org.platon.core.config.CoreConfig; 7 | 8 | @Ignore 9 | public class CmdInterfaceTest { 10 | 11 | @Test 12 | public void testCliParseForHelp(){ 13 | 14 | String[] cmds = new String[]{"--help"}; 15 | CmdInterface.call(cmds); 16 | } 17 | 18 | @Test 19 | public void testCliParse(){ 20 | 21 | System.setProperty(CoreConfig.PROPERTY_DB_DIR, "db-00001"); 22 | System.setProperty(CoreConfig.PROPERTY_DB_RESET, "yes"); 23 | 24 | String[] cmds = new String[]{"-db","db-00002","-reset","no"}; 25 | CmdInterface.call(cmds); 26 | 27 | Assert.assertEquals("db-00002", CoreConfig.getInstance().getConfig().getString(CoreConfig.PROPERTY_DB_DIR)); 28 | Assert.assertEquals(false, CoreConfig.getInstance().getConfig().getBoolean(CoreConfig.PROPERTY_DB_RESET)); 29 | } 30 | } -------------------------------------------------------------------------------- /core/src/test/java/org/platon/core/facade/PlatonFactoryTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.facade; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import org.platon.core.config.CommonConfig; 6 | import org.platon.core.config.DefaultConfig; 7 | 8 | public class PlatonFactoryTest { 9 | 10 | @Test 11 | public void testCreateByNoConfig(){ 12 | Platon platon = PlatonFactory.createPlaton(); 13 | Assert.assertNotNull(platon); 14 | } 15 | 16 | @Test 17 | public void testCreateByDefaultConfig(){ 18 | Platon platon = PlatonFactory.createPlaton(DefaultConfig.class); 19 | Assert.assertNotNull(platon); 20 | } 21 | 22 | @Test 23 | public void testCreateByCommonConfig(){ 24 | Platon platon = PlatonFactory.createPlaton(CommonConfig.class); 25 | Assert.assertNotNull(platon); 26 | } 27 | 28 | 29 | } -------------------------------------------------------------------------------- /core/src/test/java/org/platon/core/genesis/GenesisLoaderTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.core.genesis; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class GenesisLoaderTest { 7 | 8 | private final String genesisName = "genesis.json"; 9 | 10 | @Test 11 | public void loadGenesisJson() { 12 | GenesisJson genesisJson = GenesisLoader.loadGenesisJson(genesisName); 13 | Assert.assertNotNull(genesisJson.getAccounts()); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /core/src/test/resources/config/genesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "consensus": "Noproof", 4 | "energonLimit": "1388" 5 | }, 6 | "accounts": { 7 | "fG58UzwfKzAVXwYNaNUvkLSEPqYSkR25o": { 8 | "balance": "10000000000000000000000" 9 | } 10 | }, 11 | "autor": "5f2ae1c60a3038956cf3355960cb211de78bab50", 12 | "coinbase" : "5f2ae1c60a3038956cf3355960cb211de78bab50", 13 | "timestamp": "1533872936173", 14 | "parentHash": "0000000000000000000000000000000000000000000000000000000000000000", 15 | "energonLimit": "1388" 16 | } -------------------------------------------------------------------------------- /crypto/build.gradle: -------------------------------------------------------------------------------- 1 | sourceCompatibility = 1.8 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | compile project(":common") 9 | compile "org.bouncycastle:bcprov-jdk15on:1.59" 10 | compile "com.alibaba:fastjson:1.2.29" // fastjson 11 | compile group: 'commons-lang', name: 'commons-lang', version:'2.4' 12 | testCompile group: 'junit', name: 'junit', version: '4.11' 13 | } 14 | 15 | task createJavaProject << { 16 | sourceSets*.java.srcDirs*.each{ it.mkdirs() } 17 | sourceSets*.resources.srcDirs*.each{ it.mkdirs()} 18 | } -------------------------------------------------------------------------------- /crypto/src/main/java/org/platon/crypto/CheckUtil.java: -------------------------------------------------------------------------------- 1 | package org.platon.crypto; 2 | 3 | public class CheckUtil { 4 | 5 | public static void check(boolean test, String message) { 6 | if (!test) throw new IllegalArgumentException(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /crypto/src/main/java/org/platon/crypto/ECIESPublicKeyEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.crypto; 19 | 20 | import org.bouncycastle.crypto.KeyEncoder; 21 | import org.bouncycastle.crypto.params.AsymmetricKeyParameter; 22 | import org.bouncycastle.crypto.params.ECPublicKeyParameters; 23 | 24 | /** 25 | * Created by Anton Nashatyrev on 01.10.2015. 26 | */ 27 | public class ECIESPublicKeyEncoder implements KeyEncoder { 28 | @Override 29 | public byte[] getEncoded(AsymmetricKeyParameter asymmetricKeyParameter) { 30 | return ((ECPublicKeyParameters) asymmetricKeyParameter).getQ().getEncoded(false); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crypto/src/main/java/org/platon/crypto/config/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.crypto.config; 19 | 20 | import java.math.BigInteger; 21 | 22 | /** 23 | * Describes different constants specific for a blockchain 24 | * 25 | * Created by Anton Nashatyrev on 25.02.2016. 26 | */ 27 | public class Constants { 28 | public static final BigInteger SECP256K1N = new BigInteger("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16); 29 | 30 | public static final int CRYPTO_VERSION = 1; 31 | } 32 | -------------------------------------------------------------------------------- /crypto/src/main/java/org/platon/crypto/domain/WalletJson.java: -------------------------------------------------------------------------------- 1 | package org.platon.crypto.domain; 2 | 3 | /** 4 | * Temporary WalletJson Model 5 | * TODO : Wallet must rewrite 6 | */ 7 | public class WalletJson { 8 | 9 | private String address; 10 | 11 | private String publicKey; 12 | 13 | private String privateKey; 14 | 15 | public String getAddress() { 16 | return address; 17 | } 18 | 19 | public void setAddress(String address) { 20 | this.address = address; 21 | } 22 | 23 | public String getPublicKey() { 24 | return publicKey; 25 | } 26 | 27 | public void setPublicKey(String publicKey) { 28 | this.publicKey = publicKey; 29 | } 30 | 31 | public String getPrivateKey() { 32 | return privateKey; 33 | } 34 | 35 | public void setPrivateKey(String privateKey) { 36 | this.privateKey = privateKey; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /crypto/src/main/java/org/platon/crypto/jce/NewBouncyCastleProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.crypto.jce; 19 | 20 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 21 | 22 | import java.security.Provider; 23 | import java.security.Security; 24 | 25 | public final class NewBouncyCastleProvider { 26 | 27 | private static class Holder { 28 | private static final Provider INSTANCE; 29 | static{ 30 | Provider p = Security.getProvider("BC"); 31 | 32 | INSTANCE = (p != null) ? p : new BouncyCastleProvider(); 33 | 34 | INSTANCE.put("MessageDigest.ETH-KECCAK-256", "org.platon.crypto.hash.Keccak256"); 35 | INSTANCE.put("MessageDigest.ETH-KECCAK-512", "org.platon.crypto.hash.Keccak512"); 36 | } 37 | } 38 | 39 | public static Provider getInstance() { 40 | return Holder.INSTANCE; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crypto/src/main/java/org/platon/crypto/zksnark/Field.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package org.platon.crypto.zksnark; 19 | 20 | /** 21 | * Interface of abstract finite field 22 | * 23 | * @author Mikhail Kalinin 24 | * @since 05.09.2017 25 | */ 26 | interface Field { 27 | 28 | T add(T o); 29 | T mul(T o); 30 | T sub(T o); 31 | T squared(); 32 | T dbl(); 33 | T inverse(); 34 | T negate(); 35 | boolean isZero(); 36 | boolean isValid(); 37 | } 38 | -------------------------------------------------------------------------------- /crypto/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg %n 7 | 8 | 9 | DEBUG 10 | 11 | 12 | 13 | 14 | ../logs/crypto.log 15 | 16 | ../logs/crypto_%d{yyyy-MM-dd}.log 17 | 30 18 | 19 | 20 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /crypto/src/test/java/org/platon/crypto/HashUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.crypto; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import org.bouncycastle.util.encoders.Hex; 6 | 7 | public class HashUtilTest { 8 | 9 | private static final String message = "welcome to platon"; 10 | 11 | private static final String messageSha3Str = "86139924b67294e70849375a7b59531c0819e790471a607578b162211ca44871"; 12 | 13 | private static final String messageR160Str = "89af04763c4b9c3cb447af31b5e0f5756bddc76d"; 14 | 15 | @Test 16 | public void sha3() { 17 | byte[] messageSha3= HashUtil.sha3(message.getBytes()); 18 | Assert.assertEquals(Hex.toHexString(messageSha3),messageSha3Str); 19 | } 20 | 21 | @Test 22 | public void ripemd160() { 23 | byte[] messageR160= HashUtil.ripemd160(message.getBytes()); 24 | Assert.assertEquals(Hex.toHexString(messageR160),messageR160Str); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /crypto/src/test/resources/keys/5f2ae1c60a3038956cf3355960cb211de78bab50: -------------------------------------------------------------------------------- 1 | {"address":"5f2ae1c60a3038956cf3355960cb211de78bab50","privateKey":"4c63f0f5b5ef625cc5fc072eedc3dfa34a9a737489dbccf9b8e3050ea2b3cef2","publicKey":"04ee200f36d16241d7bf99e42d2d5f2239329dca7a5328f5f81f88b66c12dc478d6eef914e9a4eafadb0ad92b2f5904de1eba3549f0b82dbc07e0853cd4fe6438b"} -------------------------------------------------------------------------------- /crypto/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg %n 7 | 8 | 9 | DEBUG 10 | 11 | 12 | 13 | 14 | ../logs/crypto-test.log 15 | 16 | ../logs/crypto-test%d{yyyy-MM-dd}.log 17 | 30 18 | 19 | 20 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | // ********************************************************************** 2 | // 3 | // 配置扩展属性 4 | // 5 | // ********************************************************************** 6 | 7 | -------------------------------------------------------------------------------- /p2p/build.gradle: -------------------------------------------------------------------------------- 1 | archivesBaseName = "${rootProject.name}-p2p" 2 | 3 | dependencies { 4 | compile project(":slice") 5 | compile project(":common") 6 | compile project(":crypto") 7 | compile( 8 | "commons-collections:commons-collections:3.2.2", 9 | 'org.apache.commons:commons-configuration2:2.2', 10 | "org.apache.commons:commons-lang3:3.5", 11 | 'org.apache.httpcomponents:httpclient:4.5.3', 12 | "commons-codec:commons-codec:1.10", 13 | 'commons-configuration:commons-configuration:1.10', 14 | 'org.lmdbjava:lmdbjava:0.6.0', 15 | 'com.alibaba:fastjson:1.2.29' 16 | ) 17 | compile group: 'io.netty', name: 'netty-all', version: '4.1.28.Final' 18 | 19 | // https://mvnrepository.com/artifact/org.reflections/reflections 20 | compile group: 'org.reflections', name: 'reflections', version: '0.9.10' 21 | } 22 | 23 | 24 | buildscript { 25 | repositories { 26 | maven { 27 | url "http://maven.aliyun.com/nexus/content/groups/public/" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/ForwardMessageHook.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import com.google.protobuf.Any; 4 | import org.platon.p2p.proto.common.NodeID; 5 | import org.platon.p2p.proto.platon.Header; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | /** 12 | * @author yangzhou 13 | * @create 2018-07-26 18:17 14 | */ 15 | public class ForwardMessageHook { 16 | 17 | private static Map hooks = new ConcurrentHashMap(); 18 | 19 | public static void add(String serviceName, ForwardMessageHook.ForwardMessageCallback hook){ 20 | hooks.put(serviceName, hook); 21 | } 22 | 23 | public static void remove(String serviceName) { 24 | hooks.remove(serviceName); 25 | } 26 | 27 | 28 | 29 | public static List nextHops(Header header, Any any) { 30 | ForwardMessageHook.ForwardMessageCallback callback = hooks.get(any.getTypeUrl()); 31 | 32 | if (callback != null) { 33 | return callback.nextHops(header, any); 34 | } 35 | return null; 36 | } 37 | 38 | public static ForwardMessageHook.ForwardMessageCallback get(String serviceName) { 39 | return hooks.get(serviceName); 40 | } 41 | 42 | public interface ForwardMessageCallback { 43 | List nextHops(Header header, Any any); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/MessageHook.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import org.platon.p2p.proto.platon.PlatonMessage; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | /** 9 | * @author yangzhou 10 | * @create 2018-07-23 13:59 11 | */ 12 | public class MessageHook { 13 | 14 | 15 | private static Map hooks = new ConcurrentHashMap(); 16 | 17 | public static void add(String serviceName, MessageCallback hook){ 18 | hooks.put(serviceName, hook); 19 | } 20 | 21 | public static void remove(String serviceName) { 22 | hooks.remove(serviceName); 23 | } 24 | 25 | 26 | 27 | public static boolean isNeedProcess(PlatonMessage request) { 28 | 29 | MessageCallback callback = hooks.get(request.getBody().getData().getTypeUrl()); 30 | 31 | if (callback != null) { 32 | return callback.isNeedProcess(request); 33 | } 34 | return false; 35 | } 36 | 37 | public static MessageCallback get(String serviceName) { 38 | return hooks.get(serviceName); 39 | } 40 | 41 | public interface MessageCallback { 42 | boolean isNeedProcess(PlatonMessage request); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/NodeClientChannelHandler.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import com.google.protobuf.ByteString; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.platon.p2p.common.CodecUtils; 6 | import org.platon.p2p.proto.session.CreateSession; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class NodeClientChannelHandler extends P2pChannelHandler { 11 | 12 | private static final Logger logger = LoggerFactory.getLogger(NodeClientChannelHandler.class); 13 | 14 | private boolean isHandshakeDone = false; 15 | 16 | 17 | private ByteString remoteNodePubKey; 18 | 19 | public NodeClientChannelHandler(ByteString remoteNodeId, ByteString remoteNodePubKey) { 20 | super(); 21 | this.remoteNodeId = remoteNodeId; 22 | this.remoteNodePubKey = remoteNodePubKey; 23 | } 24 | 25 | 26 | @Override 27 | protected void handleCreateSessionRequest(ChannelHandlerContext ctx, CreateSession createSession) { 28 | 29 | } 30 | 31 | 32 | @Override 33 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 34 | logger.debug("channel is active for:" + CodecUtils.toHexString(remoteNodeId)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/NodeContext.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.platon.crypto.ECKey; 5 | import org.platon.p2p.proto.common.NodeID; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.Map; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | import java.util.concurrent.Executor; 12 | import java.util.concurrent.Executors; 13 | 14 | /** 15 | * @version 1.0.0 16 | * @author: lvxiaoyi 17 | *

18 | * Revision History: 19 | * 2018/5/17, lvxiaoyi, Initial Version. 20 | */ 21 | public class NodeContext { 22 | 23 | private static Logger logger = LoggerFactory.getLogger(NodeContext.class); 24 | 25 | private static Map relayMap = new ConcurrentHashMap<>(); 26 | 27 | public static String host; 28 | public static int port; 29 | 30 | public static ByteString localNodeId; 31 | public static ByteString address; 32 | 33 | public static byte[] publicKey; 34 | public static byte[] privateKey; 35 | public static ECKey ecKey; 36 | 37 | public static long timeIntervalForDuplicatedMessage; 38 | 39 | public static Executor executor = Executors.newCachedThreadPool(); 40 | 41 | 42 | public static String getEndpoint(){ 43 | return host + ":" + port; 44 | } 45 | public static NodeID getNodeID(){ 46 | return NodeID.newBuilder().setId(localNodeId).setEndpoint(host +":"+port).build(); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/NodeServerChannelHandler.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import org.platon.common.utils.SpringContextUtil; 5 | import org.platon.p2p.proto.session.CreateSession; 6 | import org.platon.p2p.session.CreateSessionHandler; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * @version 1.0.0 12 | * @author: lvxiaoyi 13 | *

14 | * Revision History: 15 | * 2018/8/20, lvxiaoyi, Initial Version. 16 | */ 17 | public class NodeServerChannelHandler extends P2pChannelHandler { 18 | 19 | private static final Logger logger = LoggerFactory.getLogger(NodeServerChannelHandler.class); 20 | 21 | public NodeServerChannelHandler() { 22 | super(); 23 | } 24 | 25 | protected void handleCreateSessionRequest(ChannelHandlerContext ctx, CreateSession createSession){ 26 | 27 | CreateSessionHandler createSessionHandler = SpringContextUtil.getBean("createSessionHandler"); 28 | createSessionHandler.handleCreateSessionRequest(createSession, ctx); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/common/CodecUtils.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.common; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.platon.common.utils.Numeric; 5 | 6 | public class CodecUtils { 7 | public static String toHexString(ByteString byteString){ 8 | if(byteString==null || byteString.isEmpty()){ 9 | return null; 10 | } 11 | return Numeric.toHexString(byteString.toByteArray()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/common/HeaderHelper.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.common; 2 | 3 | import org.platon.p2p.proto.common.NodeID; 4 | import org.platon.p2p.proto.common.RoutableID; 5 | import org.platon.p2p.proto.platon.Header; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * @author yangzhou 12 | * @create 2018-08-20 14:44 13 | */ 14 | public class HeaderHelper { 15 | 16 | 17 | private Header header; 18 | 19 | 20 | public static HeaderHelper build(Header header) { 21 | return new HeaderHelper(header); 22 | } 23 | public HeaderHelper(Header header) { 24 | this.header = header; 25 | } 26 | 27 | public Header getHeader() { 28 | return header; 29 | } 30 | 31 | public List destList() { 32 | return header.getDestList(); 33 | } 34 | 35 | public List viaList() { 36 | return header.getViaList(); 37 | } 38 | 39 | public String txId() { 40 | return header.getTxId(); 41 | } 42 | 43 | public List viaToDest() { 44 | List routableIDList = new ArrayList<>(); 45 | for (NodeID nodeId : header.getViaList()) { 46 | routableIDList.add(NodeUtils.toRoutableID(nodeId)); 47 | } 48 | 49 | return routableIDList; 50 | } 51 | 52 | public NodeID senderId() { 53 | return header.getVia(0); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/common/LmdbConfig.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.common; 2 | 3 | import com.typesafe.config.Config; 4 | import org.platon.common.config.ConfigProperties; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | *

LmdbConfig.java

10 | *

11 | *

Description:

12 | *

13 | *

Copyright (c) 2017. juzix.io. All rights reserved.

14 | *

15 | * 16 | * @version 1.0.0 17 | * @author: lvxiaoyi 18 | *

19 | * Revision History: 20 | * 2018/5/11, lvxiaoyi, Initial Version. 21 | */ 22 | public class LmdbConfig { 23 | private static Logger logger = LoggerFactory.getLogger(ReDiRConfig.class); 24 | 25 | private Config config; 26 | 27 | public static LmdbConfig getInstance() { 28 | return new LmdbConfig(ConfigProperties.getInstance().getConfig().getObject("lmdb").toConfig()); 29 | } 30 | 31 | public LmdbConfig(Config config) { 32 | this.config = config; 33 | } 34 | 35 | 36 | public String getLmdbNativeLib() { 37 | return config.getString("lmdbjava-native-lib"); 38 | } 39 | 40 | public String getLmdbName() { 41 | return config.getString("lmdb-name"); 42 | } 43 | 44 | public String getLmdbDataFile() { 45 | return config.getString("lmdb-data-file"); 46 | } 47 | 48 | public int getLmdbMaxReaders() { 49 | return config.getInt("lmdb-max-readers"); 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/common/PeerConfig.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.common; 2 | 3 | import com.typesafe.config.Config; 4 | import org.platon.common.config.ConfigProperties; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.List; 9 | 10 | public class PeerConfig { 11 | private static Logger logger = LoggerFactory.getLogger(PeerConfig.class); 12 | 13 | private Config config; 14 | 15 | public static PeerConfig getInstance() { 16 | return new PeerConfig(ConfigProperties.getInstance().getConfig().getObject("peer").toConfig()); 17 | } 18 | 19 | public PeerConfig(Config config) { 20 | this.config = config; 21 | } 22 | 23 | 24 | public int getPort() { 25 | return config.getInt("listen.port"); 26 | } 27 | 28 | public List getActiveNodeConfig() { 29 | return (List) config.getConfigList("active.list"); 30 | } 31 | 32 | public int getCreateSessionTimeout() { 33 | return config.getInt("create.session.timeout"); 34 | } 35 | public int getMessageResponseTimeout() { 36 | return config.getInt("message.response.timeout"); 37 | } 38 | public int getPeerConnectTimeout() { 39 | return config.getInt("peer.connect.timeout"); 40 | } 41 | 42 | public int getTimeIntervalForDuplicatedMessage() { 43 | return config.getInt("time.interval.for.duplicated.message"); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/common/ProtoBufHelper.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.common; 2 | 3 | import com.google.protobuf.ByteString; 4 | import com.google.protobuf.Internal; 5 | import com.google.protobuf.InvalidProtocolBufferException; 6 | import com.google.protobuf.Message; 7 | 8 | /** 9 | * @author yangzhou 10 | * @create 2018-08-22 14:42 11 | */ 12 | public class ProtoBufHelper { 13 | public static String getTypeNameFromTypeUrl( 14 | java.lang.String typeUrl) { 15 | int pos = typeUrl.lastIndexOf('/'); 16 | return pos == -1 ? "" : typeUrl.substring(pos + 1); 17 | } 18 | 19 | public static String getFullName(Class clazz) { 20 | return (Internal.getDefaultInstance(clazz)).getDescriptorForType().getFullName(); 21 | } 22 | 23 | 24 | 25 | public static ByteString encodeIceData(Message v) { 26 | return v.toByteString(); 27 | } 28 | 29 | 30 | 31 | public static T decodeIceData(ByteString buf, com.google.protobuf.Parser parser) { 32 | T data = null; 33 | try { 34 | data = parser.parseFrom(buf); 35 | } catch (InvalidProtocolBufferException e) { 36 | data = null; 37 | } 38 | return data; 39 | } 40 | 41 | public static T decodeIceData(byte[] buf, com.google.protobuf.Parser parser) { 42 | T data = null; 43 | try { 44 | data = parser.parseFrom(buf); 45 | } catch (InvalidProtocolBufferException e) { 46 | data = null; 47 | } 48 | return data; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/db/DB.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.db; 2 | 3 | import org.apache.commons.lang3.tuple.Pair; 4 | 5 | import java.util.List; 6 | 7 | 8 | 9 | public interface DB { 10 | 11 | final static int BigIntegerLength = 20; 12 | void set(final byte[] key, final byte[] value) throws DBException; 13 | byte[] get(final byte[] key) throws DBException; 14 | void del(final byte[] key) throws DBException; 15 | 16 | void hset(final byte[] name, final byte[] key, final byte[] value) throws DBException; 17 | byte[] hget(final byte[] name, final byte[] key) throws DBException; 18 | List> hgetAll(final byte[] name) throws DBException; 19 | void hdel(final byte[] name, final byte[] key) throws DBException; 20 | long hsize(final byte[] name)throws DBException; 21 | 22 | 23 | 24 | 25 | void zset(final byte[] name, final byte[] key, final byte[] score)throws DBException; 26 | void zdel(final byte[] name, final byte[] key) throws DBException; 27 | byte[] zget(final byte[] name, final byte[] key) throws DBException; 28 | long zrank(final byte[] name, final byte[] key) throws DBException; 29 | long zsize(final byte[] name) throws DBException; 30 | 31 | 32 | } -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/db/DBException.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.db; 2 | 3 | /** 4 | * @author Jungle 5 | * @create 2018-04-28 16:46 6 | */ 7 | public class DBException extends Exception { 8 | public DBException(final String msg) { 9 | super(msg, null); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/handler/PlatonMessageHandler.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.handler; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | *

PlatonMessageHandler.java

10 | *

11 | *

Description:

12 | *

13 | *

Copyright (c) 2017. juzix.io. All rights reserved.

14 | *

15 | * 16 | * @version 1.0.0 17 | * @author: lvxiaoyi 18 | *

19 | * Revision History: 20 | * 2018/8/30, lvxiaoyi, Initial Version. 21 | */ 22 | 23 | @Target(ElementType.TYPE) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | public @interface PlatonMessageHandler { 26 | String name(); 27 | } 28 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/handler/PlatonMessageType.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.handler; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | *

PlatonMessageType.java

10 | *

11 | *

Description:

12 | *

13 | *

Copyright (c) 2017. juzix.io. All rights reserved.

14 | *

15 | * 16 | * @version 1.0.0 17 | * @author: lvxiaoyi 18 | *

19 | * Revision History: 20 | * 2018/8/30, lvxiaoyi, Initial Version. 21 | */ 22 | @Target(ElementType.METHOD) 23 | @Retention(RetentionPolicy.RUNTIME) 24 | public @interface PlatonMessageType { 25 | String value() default ""; 26 | } 27 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/plugins/PluginFactory.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins; 2 | 3 | /** 4 | * @author yangzhou 5 | * @create 2018-04-24 15:50 6 | */ 7 | public abstract class PluginFactory { 8 | PluginFactory factory; 9 | 10 | void register(PluginFactory factory) { 11 | this.factory = factory; 12 | } 13 | 14 | 15 | TopologyPlugin create() { 16 | return factory.create(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/plugins/ResourceMap.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins; 2 | 3 | import org.platon.p2p.db.DB; 4 | import org.platon.p2p.db.DBException; 5 | import org.platon.p2p.proto.common.ResourceID; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | /** 14 | * @author yangzhou 15 | * @create 2018-07-23 10:25 16 | */ 17 | public class ResourceMap { 18 | 19 | 20 | @Autowired 21 | DB db; 22 | private static Logger logger = LoggerFactory.getLogger(ResourceMap.class); 23 | 24 | 25 | private final Set resourceCache = new HashSet<>(); 26 | 27 | 28 | 29 | public void setDb(DB db) { 30 | this.db = db; 31 | } 32 | 33 | public boolean isExist(ResourceID resourceID) { 34 | if (resourceCache.contains(resourceID)) { 35 | return true; 36 | } 37 | 38 | 39 | try { 40 | 41 | if (db.get(resourceID.getId().toByteArray()) != null) { 42 | return true; 43 | } 44 | if (db.hgetAll(resourceID.getId().toByteArray()) != null) { 45 | return true; 46 | } 47 | } catch (DBException e) { 48 | logger.error(e.getMessage()); 49 | return false; 50 | } 51 | return false; 52 | } 53 | public void add(ResourceID resourceID) { 54 | resourceCache.add(resourceID); 55 | } 56 | 57 | public boolean remove(ResourceID resourceID) { 58 | return resourceCache.remove(resourceID); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/plugins/RoutableIDComparator.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins; 2 | 3 | import org.platon.p2p.plugins.kademlia.KademliaHelp; 4 | import org.platon.p2p.proto.common.RoutableID; 5 | 6 | import java.math.BigInteger; 7 | import java.util.Comparator; 8 | 9 | /** 10 | * @author yangzhou 11 | * @create 2018-08-17 15:37 12 | */ 13 | public class RoutableIDComparator implements Comparator { 14 | private final BigInteger key; 15 | 16 | /** 17 | * @param key The NodeId relative to which the distance should be measured. 18 | */ 19 | public RoutableIDComparator(RoutableID key) 20 | { 21 | this.key = KademliaHelp.getInt(key.getId()); 22 | } 23 | 24 | /** 25 | * Compare two objects which must both be of type Node 26 | * and determine which is closest to the identifier specified in the 27 | * constructor. 28 | * 29 | * @param n1 Node 1 to compare distance from the key 30 | * @param n2 Node 2 to compare distance from the key 31 | */ 32 | @Override 33 | public int compare(RoutableID n1, RoutableID n2) 34 | { 35 | BigInteger b1 = KademliaHelp.getInt(n1.getId()); 36 | BigInteger b2 = KademliaHelp.getInt(n2.getId()); 37 | 38 | b1 = b1.xor(key); 39 | b2 = b2.xor(key); 40 | 41 | return b1.abs().compareTo(b2.abs()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/plugins/RoutingTable.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.platon.p2p.plugins.kademlia.Contact; 5 | import org.platon.p2p.proto.common.NodeID; 6 | import org.platon.p2p.proto.common.ResourceID; 7 | import org.platon.p2p.proto.common.RoutableID; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author yangzhou 13 | * @create 2018-04-24 15:55 14 | */ 15 | public interface RoutingTable { 16 | 17 | /** 18 | * @return the the next hops node-ids 19 | */ 20 | NodeID getLocalNode(); 21 | List getNextHops(NodeID destination); 22 | List getNextHops(NodeID destination, int num); 23 | 24 | List getNextHops(ResourceID destination); 25 | List getNextHops(ResourceID destination, int num); 26 | 27 | List getNextHops(RoutableID destination); 28 | List getNextHops(RoutableID destination, int num); 29 | 30 | List getNeighbors(); 31 | List getNeighbors(NodeID id, int num); 32 | List getNeighbors(ResourceID id, int num); 33 | List getNeighbors(RoutableID id, int num); 34 | 35 | List getAllNode(); 36 | 37 | String getEndPoint(ByteString destination); 38 | 39 | NodeID getNodeID(ByteString destination); 40 | 41 | void add(NodeID node); 42 | void del(NodeID node); 43 | String getTableToJson(); 44 | 45 | void setTableFromJson(String json); 46 | 47 | List getAllContacts(); 48 | } -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/plugins/TopologyPlugin.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins; 2 | 3 | import org.platon.p2p.proto.common.NodeID; 4 | import org.platon.p2p.proto.common.ResourceID; 5 | import org.platon.p2p.proto.common.RoutableID; 6 | 7 | import java.util.List; 8 | import java.util.concurrent.CompletableFuture; 9 | 10 | /** 11 | * @author yangzhou 12 | * @create 2018-04-24 15:53 13 | */ 14 | public interface TopologyPlugin { 15 | 16 | void join(NodeID remote); 17 | CompletableFuture> query(RoutableID dest); 18 | 19 | int getDistance(RoutableID source, RoutableID dest); 20 | 21 | boolean isLocalPeerResponsible(RoutableID dest); 22 | 23 | boolean isLocalPeerValidStorage(ResourceID resourceId, boolean isReplica); 24 | 25 | List getReplicaNodes(ResourceID resourceId); 26 | 27 | RoutingTable getRoutingTable(); 28 | 29 | List getBroadCastNode(RoutableID dest); 30 | } 31 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/plugins/TopologyPluginFactory.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins; 2 | 3 | /** 4 | * @author yangzhou 5 | * @create 2018-04-24 15:51 6 | */ 7 | public class TopologyPluginFactory extends PluginFactory { 8 | 9 | @Override 10 | public TopologyPlugin create() { 11 | return new KadTopologyPlugin(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/plugins/kademlia/KeyComparator.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins.kademlia; 2 | 3 | import org.platon.p2p.proto.common.NodeID; 4 | 5 | import java.math.BigInteger; 6 | import java.util.Comparator; 7 | 8 | 9 | public class KeyComparator implements Comparator 10 | { 11 | 12 | private final BigInteger key; 13 | 14 | 15 | public KeyComparator(NodeID key) 16 | { 17 | this.key = KademliaHelp.getInt(key.getId()); 18 | } 19 | 20 | 21 | @Override 22 | public int compare(NodeID n1, NodeID n2) 23 | { 24 | BigInteger b1 = KademliaHelp.getInt(n1.getId()); 25 | BigInteger b2 = KademliaHelp.getInt(n2.getId()); 26 | 27 | b1 = b1.xor(key); 28 | b2 = b2.xor(key); 29 | 30 | return b1.abs().compareTo(b2.abs()); 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/pubsub/MessageIdCache.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | /** 9 | * @author yangzhou 10 | * @create 2018-08-01 16:08 11 | */ 12 | public class MessageIdCache { 13 | 14 | private final Map> msgCache = new HashMap<>(); 15 | 16 | MessageIdCache() { 17 | 18 | } 19 | 20 | 21 | void add(String topic, String msgId) { 22 | synchronized (msgCache) { 23 | 24 | Set msgSet = msgCache.get(topic); 25 | if (msgSet == null) { 26 | msgSet = new HashSet<>(); 27 | } 28 | 29 | msgSet.add(msgId); 30 | msgCache.put(topic, msgSet); 31 | } 32 | } 33 | 34 | Set get(String topic) { 35 | synchronized (msgCache) { 36 | return msgCache.get(topic); 37 | } 38 | } 39 | 40 | void sweep(){ 41 | synchronized (msgCache) { 42 | msgCache.clear(); 43 | } 44 | } 45 | 46 | String dump() { 47 | StringBuilder stringBuilder = new StringBuilder(); 48 | synchronized (msgCache) { 49 | for (Map.Entry> entry : msgCache.entrySet()) { 50 | stringBuilder.append(String.format("topic:%s size:%d,", entry.getKey(), entry.getValue().size())); 51 | } 52 | } 53 | return stringBuilder.toString(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/pubsub/PubSubMessageHook.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import org.platon.p2p.MessageHook; 4 | import org.platon.p2p.proto.platon.PlatonMessage; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * @author yangzhou 10 | * @create 2018-07-26 10:09 11 | */ 12 | public class PubSubMessageHook implements MessageHook.MessageCallback { 13 | private static Logger logger = LoggerFactory.getLogger(PubSubMessageHook.class); 14 | @Override 15 | public boolean isNeedProcess(PlatonMessage request) { 16 | logger.trace("PubSubMessageHook need process"); 17 | 18 | return true; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/pubsub/PubSubService.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import org.platon.p2p.common.HeaderHelper; 4 | import org.platon.p2p.handler.PlatonMessageType; 5 | import org.platon.p2p.proto.pubsub.TopicMessage; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author yangzhou 11 | * @create 2018-07-24 17:56 12 | */ 13 | @Component("pubSubService") 14 | public class PubSubService { 15 | 16 | 17 | 18 | @Autowired 19 | private PubSub pubSub; 20 | 21 | public void setPubSub(PubSub pubSub) { 22 | this.pubSub = pubSub; 23 | } 24 | 25 | @PlatonMessageType("TopicMessage") 26 | public void sendMessage(TopicMessage msg, HeaderHelper header) { 27 | pubSub.sendMessage(msg, header); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/pubsub/PubSubSessionNotify.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.platon.p2p.common.NodeUtils; 5 | import org.platon.p2p.proto.common.NodeID; 6 | import org.platon.p2p.session.SessionNotify; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * @author yangzhou 12 | * @create 2018-07-24 15:35 13 | */ 14 | public class PubSubSessionNotify implements SessionNotify.SessionNotifyCallback{ 15 | private static Logger logger = LoggerFactory.getLogger(PubSubSessionNotify.class); 16 | 17 | private PubSub pubSub; 18 | 19 | private NodeID localNodeId; 20 | public PubSubSessionNotify(PubSub pubSub, NodeID localNodeId){ 21 | this.pubSub = pubSub; 22 | this.localNodeId = localNodeId; 23 | } 24 | 25 | 26 | @Override 27 | public void create(ByteString remoteNodeId) { 28 | 29 | if (remoteNodeId.equals(localNodeId.getId())){ 30 | return; 31 | } 32 | 33 | 34 | logger.debug("session on :{}", NodeUtils.getNodeIdString(remoteNodeId)); 35 | pubSub.addPeer(remoteNodeId); 36 | } 37 | 38 | @Override 39 | public void close(ByteString remoteNodeId) { 40 | if (remoteNodeId.equals(localNodeId.getId())){ 41 | return; 42 | } 43 | logger.debug("session off :{}", NodeUtils.getNodeIdString(remoteNodeId)); 44 | pubSub.removePeer(remoteNodeId); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/pubsub/TimeCache.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import org.apache.http.util.Asserts; 4 | 5 | import java.util.HashMap; 6 | import java.util.LinkedList; 7 | import java.util.Map; 8 | import java.util.Queue; 9 | 10 | /** 11 | * @author yangzhou 12 | * @create 2018-07-24 9:58 13 | */ 14 | public class TimeCache { 15 | private long span; 16 | 17 | private Map seen = new HashMap<>(); 18 | private Queue queue = new LinkedList<>(); 19 | 20 | TimeCache(long span) { 21 | this.span = span; 22 | } 23 | 24 | public void add(String msg) { 25 | seen.put(msg, System.currentTimeMillis()); 26 | queue.offer(msg); 27 | sweep(); 28 | } 29 | 30 | public boolean has(String msg) { 31 | return seen.containsKey(msg); 32 | } 33 | 34 | public void sweep() { 35 | Long current = System.currentTimeMillis(); 36 | 37 | while (true) { 38 | String msg = queue.peek(); 39 | if (msg == null) { 40 | return; 41 | } 42 | Long time = seen.get(msg); 43 | Asserts.check(time != null, "inconsistent cache state"); 44 | if (current - time > span) { 45 | queue.poll(); 46 | seen.remove(msg); 47 | } else { 48 | return; 49 | } 50 | } 51 | } 52 | // public String dump() { 53 | // return JSON.toJSONString(seen, true); 54 | // } 55 | } 56 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/redir/KeyAlgorithm.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Map; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | 7 | /** 8 | * @author yangzhou 9 | * @create 2018-07-23 11:04 10 | */ 11 | public class KeyAlgorithm { 12 | 13 | private static Map keyFunction = new ConcurrentHashMap<>(); 14 | 15 | static { 16 | add("hashrate", new HashRate()); 17 | } 18 | 19 | 20 | public static void add(String serviceType, KeyAlgorithmFunction func) { 21 | keyFunction.put(serviceType, func); 22 | } 23 | 24 | public static void remove(String serviceType) { 25 | keyFunction.remove(serviceType); 26 | } 27 | 28 | public static KeyAlgorithmFunction get(String serviceType) { 29 | return keyFunction.get(serviceType); 30 | } 31 | 32 | public interface KeyAlgorithmFunction { 33 | BigInteger apply(String key, KeySelector selector); 34 | } 35 | 36 | 37 | 38 | private static class HashRate implements KeyAlgorithmFunction{ 39 | 40 | @Override 41 | public BigInteger apply(String key, KeySelector selector) { 42 | BigInteger num = new BigInteger(key); 43 | 44 | if (num.compareTo(selector.getLowestKey()) < 0 || num.compareTo(selector.getHighestKey()) > 0) { 45 | throw new RuntimeException("out range of key space"); 46 | } 47 | 48 | return num; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/redir/KeySelectorFactory.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import org.platon.p2p.common.ReDiRConfig; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author yangzhou 10 | * @create 2018-07-25 19:48 11 | */ 12 | public class KeySelectorFactory { 13 | 14 | private static Map selectorMap = new HashMap<>(); 15 | public static KeySelector get(String serviceType) { 16 | KeySelector selector = selectorMap.get(serviceType); 17 | if (selector != null) { 18 | return selector; 19 | } 20 | 21 | selector = new KeySelector.Builder(). 22 | branchingFactor(ReDiRConfig.getInstance().getBranchingFactor(serviceType)). 23 | namespace(serviceType). 24 | level(ReDiRConfig.getInstance().getLevel(serviceType)). 25 | lowestKey(ReDiRConfig.getInstance().getLowestKey(serviceType)). 26 | highestKey(ReDiRConfig.getInstance().getHighestKey(serviceType)). 27 | startLevel(ReDiRConfig.getInstance().getStartLevel(serviceType)). 28 | keyAlgorithmFunction(KeyAlgorithm.get(ReDiRConfig.getInstance().getAlgorithm(serviceType))).build(); 29 | return selector; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/redir/ReDiRExecption.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | 4 | 5 | public class ReDiRExecption extends Exception { 6 | public ReDiRExecption(final String msg) { 7 | super(msg, null); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/redir/ReDiRForwardMessageHook.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import com.google.protobuf.Any; 4 | import com.google.protobuf.ByteString; 5 | import org.platon.p2p.ForwardMessageHook; 6 | import org.platon.p2p.common.Bytes; 7 | import org.platon.p2p.common.HeaderHelper; 8 | import org.platon.p2p.common.NodeUtils; 9 | import org.platon.p2p.proto.common.NodeID; 10 | import org.platon.p2p.proto.platon.Header; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Set; 17 | 18 | /** 19 | * @author yangzhou 20 | * @create 2018-07-26 18:57 21 | */ 22 | public class ReDiRForwardMessageHook implements ForwardMessageHook.ForwardMessageCallback { 23 | private static Logger logger = LoggerFactory.getLogger(ReDiRForwardMessageHook.class); 24 | 25 | private ServiceDiscoveryManager serviceDiscoveryManager = null; 26 | 27 | ReDiRForwardMessageHook(ServiceDiscoveryManager serviceDiscoveryManager) { 28 | this.serviceDiscoveryManager = serviceDiscoveryManager; 29 | } 30 | 31 | @Override 32 | public List nextHops(Header header, Any any) { 33 | logger.trace("receive nexthops message header:{}", header); 34 | List nextHops = new ArrayList<>(); 35 | 36 | Set listPeers = serviceDiscoveryManager.pubSub.listPeers(NodeUtils.getNodeIdString(HeaderHelper.build(header).senderId().getId())); 37 | 38 | if (listPeers == null || listPeers.isEmpty()) { 39 | return null; 40 | } 41 | 42 | listPeers.forEach(node -> { 43 | nextHops.add(NodeID.newBuilder().setId(ByteString.copyFrom(node.getKey())).build()); 44 | }); 45 | 46 | return nextHops; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/redir/ServiceDiscovery.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import org.platon.p2p.common.HeaderHelper; 4 | import org.platon.p2p.handler.PlatonMessageType; 5 | import org.platon.p2p.proto.redir.ReDiRFindMessage; 6 | import org.platon.p2p.proto.redir.ReDiRFindRespMessage; 7 | import org.platon.p2p.proto.redir.ReDiRMessage; 8 | import org.platon.p2p.proto.redir.ReDiRRespMessage; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author yangzhou 14 | * @create 2018-04-27 11:53 15 | */ 16 | @Component("serviceDiscovery") 17 | public class ServiceDiscovery { 18 | 19 | @Autowired 20 | ServiceDiscoveryManager serviceDiscoveryManager; 21 | 22 | public void setServiceDiscoveryManager(ServiceDiscoveryManager serviceDiscoveryManager) { 23 | this.serviceDiscoveryManager = serviceDiscoveryManager; 24 | } 25 | 26 | @PlatonMessageType("ReDiRMessage") 27 | public void publish(ReDiRMessage msg, HeaderHelper header) { 28 | serviceDiscoveryManager.publish(msg, header); 29 | } 30 | 31 | @PlatonMessageType("ReDiRRespMessage") 32 | public void publishResp(ReDiRRespMessage msg, HeaderHelper header) { 33 | serviceDiscoveryManager.publishResp(msg, header); 34 | } 35 | 36 | @PlatonMessageType("ReDiRFindMessage") 37 | public void discovery(ReDiRFindMessage msg, HeaderHelper header) { 38 | serviceDiscoveryManager.discovery(msg, header); 39 | } 40 | 41 | @PlatonMessageType("ReDiRFindRespMessage") 42 | public void discoveryResp(ReDiRFindRespMessage msg, HeaderHelper header) { 43 | serviceDiscoveryManager.discoveryResp(msg, header); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/redir/ServiceDiscoverySubCallback.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import org.platon.p2p.pubsub.PubSub; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * @author yangzhou 9 | * @create 2018-07-25 19:24 10 | */ 11 | public class ServiceDiscoverySubCallback implements PubSub.SubscribeCallback { 12 | private static Logger logger = LoggerFactory.getLogger(ServiceDiscoverySubCallback.class); 13 | 14 | @Override 15 | public void subscribe(String topic, byte[] data) { 16 | 17 | logger.trace("receive new data:{}", topic); 18 | 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/redir/ServiceDiscoveryUtil.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import org.apache.commons.codec.binary.Hex; 4 | import org.platon.p2p.common.ProtoBufHelper; 5 | import org.platon.p2p.db.DB; 6 | import org.platon.p2p.db.DBException; 7 | import org.platon.p2p.proto.redir.ReDiRMessage; 8 | import org.platon.p2p.proto.storage.StoredData; 9 | import org.platon.p2p.pubsub.PubSub; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.util.concurrent.CompletableFuture; 13 | 14 | 15 | 16 | public class ServiceDiscoveryUtil { 17 | 18 | private static org.slf4j.Logger logger = LoggerFactory.getLogger(ServiceDiscoveryUtil.class); 19 | 20 | private static final long LIFETIME = 100000; 21 | 22 | 23 | 24 | 25 | public static void storeLocalMessage(DB db, PubSub pubSub, ReDiRMessage msg, long now) { 26 | 27 | 28 | StoredData.Builder storedDataBuilder = StoredData.newBuilder(); 29 | 30 | 31 | 32 | 33 | storedDataBuilder.setKey(msg.getResourceId().getId()); 34 | storedDataBuilder.setValue(ProtoBufHelper.encodeIceData(msg.getEntry())); 35 | storedDataBuilder.setStorageTime(now); 36 | storedDataBuilder.setLifeTime(LIFETIME); 37 | 38 | 39 | byte[] storeBytes = ProtoBufHelper.encodeIceData(storedDataBuilder.build()).toByteArray(); 40 | 41 | try { 42 | db.hset(msg.getResourceId().getId().toByteArray(), msg.getEntry().getFrom().getBytes(), storeBytes); 43 | } catch (DBException e) { 44 | logger.error("error:", e); 45 | } 46 | 47 | 48 | CompletableFuture.runAsync(()-> { 49 | pubSub.publish(Hex.encodeHexString(msg.getResourceId().getId().toByteArray()), storeBytes); 50 | }); 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/session/ChannelAttribute.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.session; 2 | 3 | /** 4 | * @version 1.0.0 5 | * @author: lvxiaoyi 6 | *

7 | * Revision History: 8 | * 2018/8/4, lvxiaoyi, Initial Version. 9 | */ 10 | public class ChannelAttribute { 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/session/CreateSessionHandler.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.session; 2 | 3 | 4 | import io.netty.channel.ChannelHandlerContext; 5 | import org.platon.p2p.common.HeaderHelper; 6 | import org.platon.p2p.handler.PlatonMessageType; 7 | import org.platon.p2p.proto.session.CreateSession; 8 | import org.platon.p2p.proto.session.SayHello; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Component; 13 | 14 | /** 15 | * @author lvxy 16 | * @version 0.0.1 17 | * @date 2018/8/27 11:17 18 | */ 19 | @Component("createSessionHandler") 20 | public class CreateSessionHandler { 21 | 22 | private static final Logger logger = LoggerFactory.getLogger(CreateSessionHandler.class); 23 | 24 | @Autowired 25 | private SessionManager sessionManager; 26 | 27 | public void handleCreateSessionRequest(CreateSession createSession, ChannelHandlerContext ctx) { 28 | sessionManager.handleCreateSessionRequest(createSession.getClientNodeId(), createSession.getEndpoint(), createSession.getMessageHash(), createSession.getSignature(), ctx.channel()); 29 | } 30 | 31 | 32 | @PlatonMessageType("SayHello") 33 | public void sayHello(SayHello sayHello, HeaderHelper header){ 34 | sessionManager.sayHello(sayHello.getNodeId(), sayHello.getHello(), sayHello.getFeedback()); 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /p2p/src/main/java/org/platon/p2p/session/SessionNotify.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.session; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.util.Set; 8 | import java.util.concurrent.CopyOnWriteArraySet; 9 | 10 | /** 11 | * @author yangzhou 12 | * @create 2018-07-23 17:51 13 | */ 14 | public class SessionNotify { 15 | private static final Logger logger = LoggerFactory.getLogger(SessionNotify.class); 16 | 17 | private final static Set sessionListeners = new CopyOnWriteArraySet<>(); 18 | 19 | 20 | public static void addListener(SessionNotifyCallback listener){ 21 | logger.debug("addSessionFuture session notify serviceName:{}", listener); 22 | sessionListeners.add(listener); 23 | } 24 | 25 | public static void removeListener(SessionNotifyCallback listener){ 26 | sessionListeners.remove(listener); 27 | } 28 | 29 | public static void createNotify(ByteString remoteNodeId) { 30 | for (SessionNotifyCallback callback : sessionListeners) { 31 | callback.create(remoteNodeId); 32 | } 33 | } 34 | 35 | public static void closeNotify(ByteString remoteNodeId) { 36 | for (SessionNotifyCallback callback : sessionListeners) { 37 | callback.close(remoteNodeId); 38 | } 39 | } 40 | 41 | public interface SessionNotifyCallback{ 42 | void create(ByteString remoteNodeId); 43 | void close(ByteString remoteNodeId); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /p2p/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} %-5level %thread %logger{36} - %msg %n 7 | 8 | 9 | TRACE 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/DelayCacheTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.platon.common.cache.DelayCache; 5 | import org.platon.common.utils.Numeric; 6 | import org.platon.p2p.common.CodecUtils; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class DelayCacheTest { 11 | public static void main(String[] args) throws InterruptedException { 12 | DelayCache testCache = new DelayCache<>(); 13 | testCache.setTimeoutCallback((key, value) ->{ 14 | System.out.println("key:" + CodecUtils.toHexString((ByteString)key)); 15 | System.out.println("value:" + value); 16 | }); 17 | 18 | byte[] bytes = Numeric.hexStringToByteArray("0x9f6d816d91405c36d3c408f2bcdae97f5e5df182"); 19 | 20 | testCache.put(ByteString.copyFrom(bytes), 1, 3, TimeUnit.SECONDS); 21 | 22 | testCache.remove(ByteString.copyFrom(bytes)); 23 | 24 | TimeUnit.SECONDS.sleep(100); 25 | 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/ECKeyTools.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import org.platon.common.utils.Numeric; 4 | import org.platon.crypto.ECKey; 5 | import org.platon.crypto.WalletUtil; 6 | 7 | import java.nio.charset.StandardCharsets; 8 | 9 | public class ECKeyTools { 10 | public static void main(String[] args){ 11 | ECKey ecKey = new ECKey(); 12 | 13 | byte[] priKey = ecKey.getPrivKeyBytes(); 14 | byte[] pubKey = ecKey.getPubKey(); 15 | 16 | System.out.println(Numeric.toHexString(ecKey.getPrivKeyBytes())); 17 | System.out.println(Numeric.toHexString(ecKey.getPubKey())); 18 | 19 | byte[] buf = "this is a test message.".getBytes(StandardCharsets.UTF_8); 20 | 21 | byte[] encryptedBytes = WalletUtil.encrypt(buf, NodeContext.ecKey); 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/NodeClientTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.ChannelFuture; 5 | import io.netty.channel.ChannelOption; 6 | import io.netty.channel.DefaultMessageSizeEstimator; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.nio.NioSocketChannel; 9 | 10 | public class NodeClientTest { 11 | 12 | public void connect(String host, int port) { 13 | try { 14 | ChannelFuture channelFuture = connectAsync(host, port); 15 | 16 | channelFuture.sync(); 17 | 18 | channelFuture.channel().closeFuture().sync(); 19 | } catch (Exception e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | 24 | public ChannelFuture connectAsync(String host, int port) { 25 | Bootstrap b = new Bootstrap(); 26 | b.group(new NioEventLoopGroup()); 27 | b.channel(NioSocketChannel.class); 28 | 29 | b.option(ChannelOption.SO_KEEPALIVE, true); 30 | b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT); 31 | b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000); 32 | b.remoteAddress(host, port); 33 | 34 | 35 | return b.connect(); 36 | } 37 | 38 | public static void main(String[] args) throws Exception { 39 | NodeClientTest timerClient = new NodeClientTest(); 40 | timerClient.test(); 41 | 42 | } 43 | 44 | private void test(){ 45 | connect("192.168.7.113", 11001); 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/TestSeedServer.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p; 2 | 3 | import org.platon.common.config.ConfigProperties; 4 | 5 | public class TestSeedServer { 6 | public static void main(String[] args){ 7 | ConfigProperties.setConfigPath(""); 8 | NodeServer server1 = new NodeServer(); 9 | server1.startup(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/netty/TimerClientHandler.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.netty; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.SimpleChannelInboundHandler; 7 | 8 | import java.util.Date; 9 | 10 | public class TimerClientHandler extends SimpleChannelInboundHandler { 11 | 12 | private int counter; 13 | 14 | @Override 15 | protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { 16 | 17 | System.out.println("Now is : " + msg + "; the counter is:" + ++counter + " timestamp:" + (new Date())); 18 | } 19 | 20 | @Override 21 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 22 | ByteBuf message = Unpooled.buffer(TimerClient.req.length); 23 | message.writeBytes(TimerClient.req); 24 | ctx.writeAndFlush(message); 25 | } 26 | 27 | /*public void channelActive(ChannelHandlerContext ctx) throws Exception { 28 | ByteBuf message = null 29 | for(int i=0; i<10; i++){ 30 | message = Unpooled.buffer(req.length); 31 | message.writeBytes(req); 32 | ctx.writeAndFlush(message); 33 | 34 | TimeUnit.SECONDS.sleep(1); 35 | } 36 | }*/ 37 | } 38 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/netty/TimerServerHandler.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.netty; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.SimpleChannelInboundHandler; 7 | 8 | import java.util.Date; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | public class TimerServerHandler extends SimpleChannelInboundHandler { 12 | private int counter; 13 | 14 | public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception{ 15 | System.out.println("Receive order :" + msg + ", the counter is : " + ++counter); 16 | String currentTime = "QUERY TIME ORDER".equals(msg) ? new Date().toString() : "BAD ORDER"; 17 | 18 | currentTime = currentTime + System.getProperty("line.separator"); 19 | 20 | ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); 21 | TimeUnit.SECONDS.sleep(1); 22 | 23 | System.out.println("send response timestamp: " + new Date()); 24 | ctx.writeAndFlush(resp); 25 | } 26 | } -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/netty/platon/PlatonServerHandler.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.netty.platon; 2 | 3 | import com.google.protobuf.ByteString; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.SimpleChannelInboundHandler; 6 | import org.platon.common.utils.SpringContextUtil; 7 | import org.platon.p2p.proto.platon.PlatonMessage; 8 | import org.platon.p2p.session.SessionManager; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class PlatonServerHandler extends SimpleChannelInboundHandler { 13 | 14 | private static final Logger logger = LoggerFactory.getLogger(PlatonServerHandler.class); 15 | 16 | protected ByteString remoteNodeId; 17 | 18 | public ByteString getRemoteNodeId() { 19 | return remoteNodeId; 20 | } 21 | 22 | public void setRemoteNodeId(ByteString remoteNodeId) { 23 | this.remoteNodeId = remoteNodeId; 24 | } 25 | 26 | @Override 27 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 28 | super.channelActive(ctx); 29 | } 30 | 31 | @Override 32 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 33 | super.channelInactive(ctx); 34 | if(remoteNodeId!=null) { 35 | SessionManager sessionManager = SpringContextUtil.getBean("sessionManager"); 36 | sessionManager.closeSession(remoteNodeId); 37 | } 38 | } 39 | 40 | @Override 41 | protected void channelRead0(ChannelHandlerContext ctx, PlatonMessage msg) throws Exception { 42 | logger.debug("Received PlatonMessage:{}", msg); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/plugins/TestResourceMap.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.plugins; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.apache.http.util.Asserts; 5 | import org.junit.Test; 6 | import org.platon.p2p.proto.common.ResourceID; 7 | 8 | /** 9 | * @author yangzhou 10 | * @create 2018-07-23 10:49 11 | */ 12 | public class TestResourceMap { 13 | @Test 14 | public void TestAdd(){ 15 | ResourceMap resourceMap = new ResourceMap(); 16 | ResourceID resourceID = ResourceID.newBuilder().setId(ByteString.copyFrom("hello".getBytes())).build(); 17 | ResourceID resourceID2 = ResourceID.newBuilder().setId(ByteString.copyFrom("hello1".getBytes())).build(); 18 | 19 | resourceMap.add(resourceID); 20 | resourceMap.add(resourceID2); 21 | 22 | Asserts.check(resourceMap.isExist(resourceID), "is exist fail"); 23 | Asserts.check(resourceMap.remove(resourceID), "is removeSessionFuture fail"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/pubsub/PubSubRouterMock.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import org.platon.p2p.plugins.RoutingTable; 4 | 5 | public class PubSubRouterMock extends PubSubRouter{ 6 | 7 | RoutingTable routingTableMock = null; 8 | public PubSubRouterMock(RoutingTable routingTableMock) { 9 | this.routingTableMock = routingTableMock; 10 | setRoutingTable(routingTableMock); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/pubsub/PubSubSubCallbackMock.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * @author yangzhou 8 | * @create 2018-08-02 17:15 9 | */ 10 | 11 | public class PubSubSubCallbackMock implements PubSub.SubscribeCallback { 12 | private static Logger logger = LoggerFactory.getLogger(PubSubSubCallbackMock.class); 13 | 14 | @Override 15 | public void subscribe(String topic, byte[] data) { 16 | logger.trace("receive new data:{}", topic); 17 | // ServiceDiscoveryManager serviceDiscoveryManager = BeanLocator.getBean("serviceDiscoveryManager"); 18 | // serviceDiscoveryManager.subscribe(topic, data); 19 | } 20 | } -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/pubsub/PubsubMock.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | 4 | import org.platon.p2p.plugins.RoutingTable; 5 | import org.platon.p2p.router.MessageRouter; 6 | import org.platon.p2p.session.SessionNotify; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class PubsubMock extends PubSub{ 11 | private static Logger logger = LoggerFactory.getLogger(PubsubMock.class); 12 | 13 | 14 | 15 | public PubsubMock(RoutingTable routingTableMock, MessageRouter messageRouter){ 16 | this.pubSubRouter = new PubSubRouterMock(routingTableMock); 17 | this.setRoutingTable(routingTableMock); 18 | this.setMessageRouter(messageRouter); 19 | this.pubSubRouter.setMessageRouter(messageRouter); 20 | this.pubSubRouter.attach(this); 21 | //logger.debug("add sessionNotify"); 22 | try { 23 | SessionNotify.addListener(new PubSubSessionNotify(this, routingTableMock.getLocalNode())); 24 | } catch (Exception e) { 25 | //logger.error(e); 26 | } 27 | } 28 | 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/pubsub/TimeCacheTest.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.pubsub; 2 | 3 | import org.apache.http.util.Asserts; 4 | import org.junit.Test; 5 | 6 | /** 7 | * @author yangzhou 8 | * @create 2018-07-31 13:47 9 | */ 10 | public class TimeCacheTest { 11 | 12 | @Test 13 | public void testTimeCache() throws InterruptedException { 14 | TimeCache timeCache = new TimeCache(1000); 15 | 16 | for (int i = 0; i < 1000; i++) { 17 | timeCache.add(String.valueOf(i)); 18 | } 19 | 20 | Thread.sleep(1001); 21 | timeCache.sweep(); 22 | 23 | for (int i = 0; i < 1000; i++) { 24 | Asserts.check(!timeCache.has(String.valueOf(i)), "has expired element:" + i); 25 | } 26 | 27 | for (int i = 1001; i < 2000; i++) { 28 | timeCache.add(String.valueOf(i)); 29 | } 30 | 31 | for (int i = 1001; i < 2000; i++) { 32 | Asserts.check(timeCache.has(String.valueOf(i)), "no has element:" + i); 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/redir/ReDiRClusterNode.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import org.platon.p2p.db.DB; 4 | import org.platon.p2p.plugins.RoutingTableMock; 5 | import org.platon.p2p.pubsub.PubSub; 6 | import org.platon.p2p.pubsub.PubSubSessionNotify; 7 | import org.platon.p2p.router.MessageRouterMock; 8 | 9 | 10 | public class ReDiRClusterNode { 11 | ReDiRClusterNode(PubSub pubSub, DB db, MessageRouterMock messageRouter, 12 | ServiceDiscoveryManager serviceDiscoveryManager, 13 | PubSubSessionNotify notify, RoutingTableMock routingTable) { 14 | this.pubSub = pubSub; 15 | this.db = db; 16 | this.messageRouter = messageRouter; 17 | this.serviceDiscoveryManager = serviceDiscoveryManager; 18 | this.notify = notify; 19 | this.routingTable = routingTable; 20 | } 21 | PubSubSessionNotify notify; 22 | PubSub pubSub; 23 | DB db; 24 | MessageRouterMock messageRouter; 25 | ServiceDiscoveryManager serviceDiscoveryManager; 26 | RoutingTableMock routingTable; 27 | } -------------------------------------------------------------------------------- /p2p/src/test/java/org/platon/p2p/redir/ServiceDiscoverManagerMock.java: -------------------------------------------------------------------------------- 1 | package org.platon.p2p.redir; 2 | 3 | import org.platon.p2p.db.DB; 4 | import org.platon.p2p.plugins.RoutingTable; 5 | import org.platon.p2p.pubsub.PubSub; 6 | import org.platon.p2p.router.MessageRouter; 7 | 8 | public class ServiceDiscoverManagerMock extends ServiceDiscoveryManager { 9 | 10 | ServiceDiscoverManagerMock(PubSub pubSub, MessageRouter messageRouter, DB db, RoutingTable routingTable){ 11 | this.pubSub = pubSub; 12 | this.messageRouter = messageRouter; 13 | this.db = db; 14 | this.reDiR = new ReDiR(); 15 | this.routingTable = routingTable; 16 | 17 | 18 | reDiR.pubSub = pubSub; 19 | reDiR.db = db; 20 | reDiR.messageRouter = messageRouter; 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /p2p/src/test/resources/config/node1/node.conf: -------------------------------------------------------------------------------- 1 | node = { 2 | ip=127.0.0.1 3 | port=11001 4 | public-key=0x044c73f76a65ada74e582fecfe576043657b61a71bdff3f21cf00e3a4f3a4a19212a7510efbe32c7d1f4d041b5cea3b1d0a5f3238af89f4f42b256b3d95702ec97 5 | private-key=0x74f77061f293128b3165cb5bdbe829b0b80befebb6659c224f08a4d26a04ad0f 6 | #in seconds 7 | create.session.timeout = 1011 8 | 9 | #in seconds, message.response.timeout > create.session.timeout 10 | message.response.timeout = 1211 11 | #in seconds 12 | peer.connect.timeout = 2 13 | 14 | #in seconds 15 | time.interval.for.duplicated.message = 3 16 | 17 | active.list = 18 | [ 19 | { 20 | ip=127.0.0.1 21 | port=11000 22 | public-key=0x0402720f70c4ab72ad781fbc77be02e30f1e67e98ac9bd2caeb26105e4c2ff637861feae41e783e792693da2d7adae039e058de525c8114cce3de76297dd23610e 23 | } 24 | ] 25 | } 26 | 27 | kad.plugin = { 28 | id-length = 20 29 | restore-interval = 50000 30 | response-timeout = 1 31 | operation-timeout = 0 32 | max-concurrent-messages-transiting = 1 33 | K-value = 8 34 | replacement-cache-size = 8 35 | stale-times = 8 36 | } 37 | 38 | lmdb = { 39 | lmdbjava-native-lib = "lmdb\\liblmdb.dll" 40 | lmdb-data-file = "data\\platon.db" 41 | lmdb-name = platon_p2p 42 | lmdb-max-readers = 30 43 | } 44 | 45 | redir = { 46 | hashrate = { 47 | branching-factor = 10 48 | level = 3 49 | lowest-key = 1 50 | highest-key = 100 51 | start-level = 2s 52 | algorithm = hashrate 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /p2p/src/test/resources/config/node2/node.conf: -------------------------------------------------------------------------------- 1 | node = { 2 | ip=127.0.0.1 3 | port=11002 4 | public-key=0x04a9f61f6a5e7bfbe567cba25133f6aced2740a90c0959075b87bbc4fc12889824ab48ab2d6cfe4c541e9eadef1b66741e7a97811f6fddced4f3b32e3e101c255f 5 | private-key=0x27306998a17f0779b10f0785d8432591c1ae6a15132a2309a22fbbee1417afd4 6 | #in seconds 7 | create.session.timeout = 1011 8 | 9 | #in seconds, message.response.timeout > create.session.timeout 10 | message.response.timeout = 1211 11 | #in seconds 12 | peer.connect.timeout = 2 13 | 14 | #in seconds 15 | time.interval.for.duplicated.message = 3 16 | active.list = 17 | [ 18 | { 19 | ip=127.0.0.1 20 | port=11000 21 | public-key=0x0402720f70c4ab72ad781fbc77be02e30f1e67e98ac9bd2caeb26105e4c2ff637861feae41e783e792693da2d7adae039e058de525c8114cce3de76297dd23610e 22 | } 23 | ] 24 | } 25 | 26 | kad.plugin = { 27 | id-length = 20 28 | restore-interval = 50000 29 | response-timeout = 1 30 | operation-timeout = 0 31 | max-concurrent-messages-transiting = 1 32 | K-value = 8 33 | replacement-cache-size = 8 34 | stale-times = 8 35 | } 36 | 37 | lmdb = { 38 | lmdbjava-native-lib = "lmdb\\liblmdb.dll" 39 | lmdb-data-file = "data\\platon.db" 40 | lmdb-name = platon_p2p 41 | lmdb-max-readers = 30 42 | } 43 | 44 | redir = { 45 | hashrate = { 46 | branching-factor = 10 47 | level = 3 48 | lowest-key = 1 49 | highest-key = 100 50 | start-level = 2s 51 | algorithm = hashrate 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /p2p/src/test/resources/config/seed/node.conf: -------------------------------------------------------------------------------- 1 | node = { 2 | ip=127.0.0.1 3 | port=11000 4 | public-key=0x0402720f70c4ab72ad781fbc77be02e30f1e67e98ac9bd2caeb26105e4c2ff637861feae41e783e792693da2d7adae039e058de525c8114cce3de76297dd23610e 5 | private-key=0x53a200788bb50856b89b0e26366d811445cb0817177d4c2bcb8cf5d1a482cb09 6 | #in seconds 7 | create.session.timeout = 1011 8 | 9 | #in seconds, message.response.timeout > create.session.timeout 10 | message.response.timeout = 1211 11 | #in seconds 12 | peer.connect.timeout = 2 13 | 14 | #in seconds 15 | time.interval.for.duplicated.message = 3 16 | active.list = 17 | [ 18 | ] 19 | } 20 | 21 | kad.plugin = { 22 | id-length = 20 23 | restore-interval = 50000 24 | response-timeout = 1 25 | operation-timeout = 0 26 | max-concurrent-messages-transiting = 1 27 | K-value = 8 28 | replacement-cache-size = 8 29 | stale-times = 8 30 | } 31 | 32 | lmdb = { 33 | lmdbjava-native-lib = "lmdb\\liblmdb.dll" 34 | lmdb-data-file = "data\\platon.db" 35 | lmdb-name = platon_p2p 36 | lmdb-max-readers = 30 37 | } 38 | 39 | redir = { 40 | hashrate = { 41 | branching-factor = 10 42 | level = 3 43 | lowest-key = 1 44 | highest-key = 100 45 | start-level = 2s 46 | algorithm = hashrate 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'platon' 2 | include 'slice' 3 | include 'account' 4 | include 'vm' 5 | include 'storage' 6 | include 'crypto' 7 | include 'consensus' 8 | include 'core' 9 | include 'common' 10 | include 'p2p' 11 | include 'trie' 12 | include 'tests' 13 | 14 | -------------------------------------------------------------------------------- /slice/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: "com.google.protobuf" 3 | apply plugin: 'idea' 4 | 5 | def grpcVersion = '1.15.0' 6 | def protoVersion = '3.6.1' 7 | 8 | protobuf { 9 | protoc { 10 | artifact = "com.google.protobuf:protoc:${protoVersion}" 11 | } 12 | plugins { 13 | grpc { 14 | artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" 15 | } 16 | } 17 | generateProtoTasks { 18 | all()*.plugins { 19 | grpc { 20 | outputSubDir = "java" 21 | } 22 | } 23 | } 24 | 25 | generatedFilesBaseDir = "$projectDir/src" 26 | } 27 | 28 | sourceSets { 29 | main { 30 | proto { 31 | srcDir 'src/main/proto' 32 | include '**/*.proto' 33 | } 34 | } 35 | } 36 | 37 | 38 | dependencies { 39 | compile( 40 | "com.google.protobuf:protobuf-java:${protoVersion}", 41 | ) 42 | compile group: 'io.netty', name: 'netty-all', version: '4.1.28.Final' 43 | 44 | compile "com.google.api.grpc:proto-google-common-protos:1.12.0" 45 | compile "io.grpc:grpc-alts:${grpcVersion}" 46 | compile "io.grpc:grpc-netty:${grpcVersion}" 47 | compile "io.grpc:grpc-protobuf:${grpcVersion}" 48 | compile "io.grpc:grpc-stub:${grpcVersion}" 49 | 50 | testCompile "io.grpc:grpc-testing:${grpcVersion}" 51 | } 52 | 53 | 54 | buildscript { 55 | repositories { 56 | maven { 57 | url "http://maven.aliyun.com/nexus/content/groups/public/" 58 | } 59 | } 60 | dependencies { 61 | classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.6' 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/account.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package platon.account; 4 | 5 | option java_package = "org.platon.core.proto"; 6 | option java_outer_classname = "AccountMessage"; 7 | option java_string_check_utf8 = true; 8 | option java_multiple_files = true; 9 | 10 | message AccountProto { 11 | bytes balance = 1; 12 | bytes extraRoot = 2; 13 | bytes binHash = 3; 14 | bytes permissionRoot = 4; 15 | } 16 | 17 | message PermissionAddrProto { 18 | BytesList addressList = 1; 19 | BytesList urlList = 2; 20 | } 21 | message BytesList { 22 | repeated bytes ele=1; 23 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/base.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.platon.common.proto"; 4 | option java_outer_classname = "BaseProto"; 5 | 6 | message BaseInt { 7 | int32 intData = 1; 8 | } 9 | 10 | message BaseLong { 11 | int64 longData = 1; 12 | } 13 | 14 | message BaseString { 15 | string stringData = 1; 16 | } 17 | 18 | message BaseBytesList { 19 | repeated bytes bytesListData = 1; 20 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/block.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.platon.core.block.proto"; 4 | option java_outer_classname = "BlockProto"; 5 | 6 | message Block { 7 | bytes headerbytes = 1; 8 | repeated bytes transactionbytes = 2; 9 | repeated bytes unclesbytes = 3; 10 | repeated bytes signatures = 4; 11 | } 12 | 13 | message BlockInfo { 14 | int64 number = 1; 15 | bytes totalDifficulty = 2; 16 | bytes parentHash = 3; 17 | repeated bytes children = 4; 18 | repeated bytes bloomlog = 5; 19 | } 20 | 21 | message TransactionPosition { 22 | bytes blockHash = 1; 23 | int32 index = 2; 24 | } 25 | message BlockReceipts { 26 | repeated bytes txreceipts = 1; 27 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/blockheader.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | 4 | 5 | option java_package = "org.platon.core.block.proto"; 6 | option java_outer_classname = "BlockHeaderProto"; 7 | 8 | 9 | message BlockHeader { 10 | int64 timestamp = 1; 11 | int64 number = 2; 12 | bytes parentHash = 3; 13 | bytes stateRoot = 4; 14 | bytes permissionRoot = 5; 15 | bytes dposRoot = 6; 16 | bytes transactionRoot = 7; 17 | bytes transferRoot = 8; 18 | bytes votingRoot = 9; 19 | bytes receiptRoot = 10; 20 | bytes bloomLog = 11; 21 | bytes energonUsed = 12; 22 | bytes energonCeiling = 13; 23 | bytes difficulty = 14; 24 | bytes extraData = 15; 25 | bytes author = 16; 26 | bytes coinbase = 17; 27 | } 28 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/dataword.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package platon.block; 4 | 5 | 6 | option java_package = "org.platon.core.proto"; 7 | option java_outer_classname = "DatawordProto"; 8 | option java_multiple_files = true; 9 | 10 | message DataWordMessage { 11 | bytes data = 1; 12 | } 13 | 14 | message EmptyBytesMessage { 15 | bytes data = 1; 16 | } 17 | 18 | message IntMessage { 19 | int32 data = 1; 20 | } 21 | 22 | 23 | message BlockIdentifierMessage { 24 | bytes hash = 1; 25 | int64 number = 2; 26 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/indexBlockInfo.proto: -------------------------------------------------------------------------------- 1 | 2 | 3 | syntax = "proto3"; 4 | 5 | package platon.block; 6 | 7 | option java_package = "org.platon.core.proto"; 8 | option java_outer_classname = "BlockInfoProto"; 9 | option java_multiple_files = true; 10 | 11 | message BlockInfo { 12 | bytes hash = 1; 13 | bool mainChain = 2; 14 | bytes totalDifficulty = 3; 15 | } 16 | 17 | message BlockInfoList { 18 | repeated BlockInfo blockInfoList = 1; 19 | } 20 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/message/errno.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package platon.message; 4 | 5 | option java_package = "org.platon.slice.message"; 6 | option java_outer_classname = "ResultCodeMessage"; 7 | option java_string_check_utf8 = true; 8 | 9 | enum ResultCode { 10 | SUCCESS = 0; 11 | FAIL = 1; 12 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/message/request.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package platon.message; 4 | 5 | 6 | import "org/platon/core/transaction.v2.proto"; 7 | 8 | option java_package = "org.platon.slice.message.request"; 9 | option java_outer_classname = "TransactionRequestProto"; 10 | option java_string_check_utf8 = true; 11 | option java_multiple_files = true; 12 | 13 | message TransactionBaseRequest { 14 | platon.tx.TransactionBody body = 1; 15 | string signature = 2; 16 | string from = 3; 17 | } 18 | 19 | message GetTransactionReceiptByHashRequest{ 20 | string txHash = 1; 21 | } 22 | 23 | message VoidRequest { 24 | 25 | } 26 | 27 | message GetTransactionCountRequest{ 28 | string address = 1; 29 | string blockParams = 2; 30 | } 31 | 32 | message GetBalanceRequest{ 33 | string address = 1; 34 | string blockParams = 2; 35 | } 36 | 37 | message GetBlockTransactionCountByHashRequest { 38 | string blockHash = 1; 39 | } 40 | 41 | message GetBlockTransactionCountByNumberRequest { 42 | string blockNumber = 1; 43 | } 44 | 45 | message GetBlockByHashRequest { 46 | string blockHash = 1; 47 | bool returnFull = 2; 48 | } 49 | 50 | message GetBlockByNumberRequest{ 51 | string blockNumber = 1; 52 | bool returnFull = 2; 53 | } 54 | 55 | message GetTransactionByHashRequest { 56 | string txHash = 1; 57 | } 58 | 59 | message GetTransactionByBlockHashAndIndexRequest { 60 | string blockHash = 1; 61 | sint64 index = 2; 62 | } 63 | 64 | message GetTransactionByBlockNumberAndIndexRequest { 65 | string blockNumber = 1; 66 | sint64 index = 2; 67 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/transaction.v2.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package platon.tx; 4 | 5 | import "google/protobuf/any.proto"; 6 | 7 | option java_package = "org.platon.core.transaction.proto"; 8 | option java_outer_classname = "TransactionProto"; 9 | option java_multiple_files = true; 10 | 11 | enum TransactionType { 12 | TRANSACTION = 0; 13 | VOTE = 1; 14 | CONTRACT_DEPLOY = 2; 15 | CONTRACT_CALL = 3; 16 | TRANSACTION_MPC = 4; 17 | QUERY_CALL = 5; 18 | PERMISSION_UPDATE = 6; 19 | } 20 | 21 | message TransactionBody { 22 | TransactionType type = 1; 23 | bytes value = 2; 24 | bytes receiveAddress = 3; 25 | 26 | int64 referenceBlockNum = 6; 27 | bytes referenceBlockHash = 7; 28 | bytes energonPrice = 8; 29 | bytes energonLimit = 9; 30 | google.protobuf.Any data = 10; 31 | } 32 | 33 | message Transaction { 34 | TransactionBody body = 1; 35 | bytes signature = 2; 36 | } 37 | 38 | 39 | message ContractDeployRequest { 40 | string className = 1; 41 | bytes data = 2; 42 | } 43 | 44 | message ContractRequest { 45 | string operation = 1; 46 | string className = 2; 47 | bytes data = 3; 48 | } 49 | 50 | message MPCTransactionRequest { 51 | string operation = 1; 52 | string className = 2; 53 | bytes data = 3; 54 | repeated string partners= 4; 55 | repeated string results = 5; 56 | bytes inData = 6; 57 | map nodeIdAddrMap= 7; 58 | string algorithmId = 8; 59 | map extraArgs = 9; 60 | string mpcContractAddr = 10; 61 | } 62 | 63 | 64 | message defaultRequestData { 65 | bytes data = 1; 66 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/transactionInfo.proto: -------------------------------------------------------------------------------- 1 | 2 | 3 | syntax = "proto3"; 4 | 5 | package platon.block; 6 | 7 | import "org/platon/core/transactionReceipt.v2.proto"; 8 | 9 | option java_package = "org.platon.core.proto"; 10 | option java_outer_classname = "TransactionInfoProto"; 11 | option java_multiple_files = true; 12 | 13 | message TransactionInfoMessage { 14 | platon.tx.TransactionReceiptBase receipt = 1; 15 | bytes blockHash = 2; 16 | bytes parentBlockHash = 3; 17 | int64 index = 4; 18 | } 19 | 20 | message TransactionInfoMessageList { 21 | repeated TransactionInfoMessage txInfoList = 1; 22 | } 23 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/core/transactionReceipt.v2.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | 4 | 5 | package platon.tx; 6 | 7 | option java_package = "org.platon.core.transaction.proto"; 8 | option java_outer_classname = "TransactionReceiptProto"; 9 | 10 | message LogEntry { 11 | bytes address = 1; 12 | repeated bytes topic = 2; 13 | bytes data = 3; 14 | } 15 | 16 | message TransactionReceiptBase { 17 | bytes energonUsed = 1; 18 | bytes cumulativeEnergon = 2; 19 | bytes stateRoot = 3; 20 | bytes bloomFilter = 4; 21 | bytes executionResult = 5; 22 | repeated LogEntry logs = 6; 23 | 24 | 25 | 26 | 27 | 28 | 29 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/attach/attach.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package org.platon.p2p.proto.attach; 5 | 6 | import "org/platon/p2p/common/common.proto"; 7 | 8 | 9 | option java_multiple_files = true; 10 | option java_package = "org.platon.p2p.proto.attach"; 11 | option java_outer_classname = "AttachProtos"; 12 | 13 | message AttachMessage { 14 | org.platon.p2p.proto.common.NodeID nodeId = 1; 15 | } 16 | 17 | message AttachRespMessage { 18 | org.platon.p2p.proto.common.NodeID nodeId = 1; 19 | } 20 | 21 | message PingMessage { 22 | int32 payloadLength = 1; 23 | } 24 | 25 | message PongMessage { 26 | int64 responseId = 1; 27 | int64 responseTime = 2; 28 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/common/common.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package org.platon.p2p.proto.common; 5 | 6 | 7 | option java_multiple_files = true; 8 | option java_package = "org.platon.p2p.proto.common"; 9 | option java_outer_classname = "CommonProtos"; 10 | 11 | message RoutableID { 12 | enum DestinationType { 13 | NODEIDTYPE = 0; 14 | RESOURCEIDTYPE = 1; 15 | OPAQUEIDTYPE = 2; 16 | } 17 | 18 | DestinationType type = 1; 19 | bytes id = 2; 20 | } 21 | 22 | message NodeID { 23 | bytes id = 1; 24 | 25 | 26 | string endpoint = 2; 27 | 28 | string relay = 3; 29 | 30 | 31 | bytes pubKey = 4; 32 | } 33 | 34 | message ResourceID { 35 | bytes id = 1; 36 | } 37 | 38 | message OpaqueID { 39 | bytes id = 1; 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/consensus/bftmessage.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package org.platon.p2p.proto.consensus; 4 | 5 | 6 | option java_multiple_files = true; 7 | option java_package = "org.platon.p2p.proto.consensus"; 8 | option java_outer_classname = "Bftprotos"; 9 | 10 | 11 | message PrepareAckMessage { 12 | bytes blockHash = 1; 13 | bytes signature = 2; 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/platonmessage.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package org.platon.p2p.proto.platon; 4 | import "google/protobuf/any.proto"; 5 | import "org/platon/p2p/common/common.proto"; 6 | 7 | 8 | option java_multiple_files = true; 9 | option java_package = "org.platon.p2p.proto.platon"; 10 | option java_outer_classname = "PlatonProtos"; 11 | 12 | message Header { 13 | string version = 1; 14 | string txId = 2; 15 | repeated org.platon.p2p.proto.common.NodeID via = 3; 16 | repeated org.platon.p2p.proto.common.RoutableID dest = 4; 17 | int32 ttl = 5; 18 | string msgType = 6; 19 | 20 | } 21 | 22 | message Body { 23 | google.protobuf.Any data = 1; 24 | } 25 | 26 | message PlatonMessage { 27 | Header header = 1; 28 | Body body = 2; 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/plugin/plugin.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package org.platon.p2p.proto.plugin; 4 | 5 | import "org/platon/p2p/common/common.proto"; 6 | 7 | 8 | option java_multiple_files = true; 9 | option java_package = "org.platon.p2p.proto.plugin"; 10 | option java_outer_classname = "PluginProtos"; 11 | 12 | message JoinMessage { 13 | org.platon.p2p.proto.common.NodeID nodeId = 1; 14 | } 15 | 16 | message JoinRespMessage { 17 | repeated org.platon.p2p.proto.common.NodeID nodeId = 1; 18 | } 19 | 20 | message QueryMessage { 21 | org.platon.p2p.proto.common.RoutableID routableId = 1; 22 | } 23 | 24 | 25 | message QueryRespMessage { 26 | repeated org.platon.p2p.proto.common.NodeID nodeId = 1; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/pubsub/pubsub.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package org.platon.p2p.proto.pubsub; 4 | import "org/platon/p2p/common/common.proto"; 5 | 6 | 7 | option java_multiple_files = true; 8 | option java_package = "org.platon.p2p.proto.pubsub"; 9 | option java_outer_classname = "PubsubProtos"; 10 | 11 | message SubMessage { 12 | 13 | string topic = 1; 14 | 15 | 16 | bool sub = 2; 17 | 18 | 19 | bytes nodeId = 3; 20 | } 21 | 22 | message EntryMessage { 23 | 24 | bytes fromNodeId = 1; 25 | 26 | 27 | string key = 2; 28 | 29 | 30 | string topic = 3; 31 | 32 | 33 | bytes data = 4; 34 | } 35 | 36 | message IHaveMessage { 37 | 38 | string topic = 1; 39 | 40 | 41 | repeated string messageId = 2; 42 | } 43 | 44 | 45 | message IWantMessage { 46 | 47 | string topic = 1; 48 | 49 | 50 | repeated string messageId = 2; 51 | } 52 | 53 | message GraftMessage { 54 | 55 | repeated string topic = 1; 56 | 57 | 58 | bytes nodeId = 2; 59 | } 60 | 61 | 62 | message PruneMessage { 63 | 64 | bytes nodeId = 1; 65 | 66 | 67 | repeated string topic = 2; 68 | } 69 | 70 | 71 | message ControlMessage { 72 | repeated IHaveMessage ihave = 1; 73 | repeated IWantMessage iwant = 2; 74 | GraftMessage graft = 3; 75 | PruneMessage prune = 4; 76 | } 77 | 78 | message TopicMessage { 79 | bytes fromNodeId = 1; 80 | SubMessage subscribe = 2; 81 | repeated EntryMessage publishedEntry = 3; 82 | ControlMessage control = 4; 83 | } -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/redir/redir.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package org.platon.p2p.proto.redir; 5 | import "org/platon/p2p/common/common.proto"; 6 | 7 | 8 | option java_multiple_files = true; 9 | option java_package = "org.platon.p2p.proto.redir"; 10 | option java_outer_classname = "RedirProtos"; 11 | 12 | 13 | 14 | message ServiceEntry { 15 | string serviceType = 1; 16 | string describe = 2; 17 | string sourceKey = 3; 18 | string from = 4; 19 | string url = 5; 20 | } 21 | 22 | message ReDiRMessage { 23 | org.platon.p2p.proto.common.ResourceID resourceId = 1; 24 | ServiceEntry entry = 2; 25 | } 26 | message ReDiRRespMessage { 27 | repeated string key = 1; 28 | } 29 | 30 | message ReDiRFindMessage { 31 | org.platon.p2p.proto.common.ResourceID resourceId = 1; 32 | string findKey = 2; 33 | } 34 | 35 | message ReDiRFindRespMessage { 36 | org.platon.p2p.proto.common.ResourceID resourceId = 1; 37 | repeated ServiceEntry entry = 2; 38 | repeated string key = 3; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /slice/src/main/proto/org/platon/p2p/session/session.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package org.platon.p2p.proto.session; 4 | import "org/platon/p2p/common/common.proto"; 5 | 6 | 7 | option java_multiple_files = true; 8 | option java_package = "org.platon.p2p.proto.session"; 9 | option java_outer_classname = "SessionProtos"; 10 | 11 | message CreateSession { 12 | bytes clientNodeId = 1; 13 | 14 | 15 | string endpoint = 2; 16 | 17 | 18 | bytes messageHash = 3; 19 | 20 | 21 | bytes signature = 4; 22 | } 23 | 24 | message SayHello { 25 | bytes nodeId = 1; 26 | string hello = 2; 27 | bool feedback = 3; 28 | } -------------------------------------------------------------------------------- /slice/src/test/java/org/platon/slice/grpc/StreamObserverManager.java: -------------------------------------------------------------------------------- 1 | package org.platon.slice.grpc; 2 | 3 | import io.grpc.stub.StreamObserver; 4 | 5 | import java.util.concurrent.locks.Condition; 6 | import java.util.concurrent.locks.ReentrantLock; 7 | 8 | 9 | public class StreamObserverManager implements StreamObserver { 10 | 11 | private ReentrantLock lock = new ReentrantLock(); 12 | private Condition condition = lock.newCondition(); 13 | private T response ; 14 | private boolean endFlag = false; 15 | private Throwable e; 16 | 17 | @Override 18 | public void onNext(T value) { 19 | this.response = value; 20 | } 21 | 22 | @Override 23 | public void onError(Throwable t) { 24 | t.printStackTrace(); 25 | this.e = t; 26 | endFlag = true; 27 | signal(); 28 | } 29 | 30 | @Override 31 | public void onCompleted() { 32 | endFlag = true; 33 | signal(); 34 | } 35 | 36 | public void signal(){ 37 | try { 38 | lock.lock(); 39 | 40 | condition.signal(); 41 | 42 | }catch (Exception e) { 43 | e.printStackTrace(); 44 | }finally { 45 | lock.unlock(); 46 | } 47 | } 48 | 49 | public T getResponse() throws Exception { 50 | lock.lock(); 51 | try { 52 | if(!endFlag){ 53 | 54 | condition.await(); 55 | 56 | } 57 | if (e != null) { 58 | throw new Exception(e); 59 | } 60 | if (null != this.response) { 61 | return this.response; 62 | } 63 | }catch (Exception e){ 64 | throw e; 65 | }finally { 66 | lock.unlock(); 67 | } 68 | return null; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /storage/build.gradle: -------------------------------------------------------------------------------- 1 | sourceCompatibility = 1.8 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | compile project(":slice") 9 | compile project(":crypto") 10 | compile "org.iq80.leveldb:leveldb:0.10" //LevelDB 11 | compile "org.rocksdb:rocksdbjni:5.11.3" //RocksDB 12 | compile "com.google.protobuf:protobuf-java:3.5.1" 13 | compile "org.bouncycastle:bcprov-jdk15on:1.59" 14 | testCompile "org.springframework:spring-test:${springVersion}" 15 | testCompile group: 'junit', name: 'junit', version: '4.11' 16 | } 17 | 18 | task createJavaProject << { 19 | sourceSets*.java.srcDirs*.each{ it.mkdirs() } 20 | sourceSets*.resources.srcDirs*.each{ it.mkdirs()} 21 | } -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/AbstractChainedSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public abstract class AbstractChainedSource implements Source { 4 | 5 | private Source source; 6 | protected boolean flushSource; 7 | 8 | 9 | protected AbstractChainedSource() { 10 | } 11 | 12 | public AbstractChainedSource(Source source) { 13 | this.source = source; 14 | } 15 | 16 | 17 | protected void setSource(Source src) { 18 | source = src; 19 | } 20 | 21 | public Source getSource() { 22 | return source; 23 | } 24 | 25 | public void setFlushSource(boolean flushSource) { 26 | this.flushSource = flushSource; 27 | } 28 | 29 | 30 | @Override 31 | public synchronized boolean flush() { 32 | boolean ret = flushImpl(); 33 | if (flushSource) { 34 | ret |= getSource().flush(); 35 | } 36 | return ret; 37 | } 38 | 39 | 40 | protected abstract boolean flushImpl(); 41 | } 42 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/AsyncFlushable.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import com.google.common.util.concurrent.ListenableFuture; 4 | 5 | public interface AsyncFlushable { 6 | 7 | 8 | void flipStorage() throws InterruptedException; 9 | 10 | 11 | ListenableFuture flushAsync() throws InterruptedException; 12 | } 13 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/BatchSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import java.util.Map; 4 | 5 | public interface BatchSource extends Source { 6 | 7 | void updateBatch(Map rows); 8 | } 9 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/BatchSourceWriter.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class BatchSourceWriter extends AbstractChainedSource { 7 | 8 | private Map buffer = new HashMap<>(); 9 | 10 | public BatchSourceWriter(BatchSource src) { 11 | super(src); 12 | } 13 | 14 | private BatchSource getBatchSource() { 15 | return (BatchSource) getSource(); 16 | } 17 | 18 | @Override 19 | public synchronized void delete(Key key) { 20 | buffer.put(key, null); 21 | } 22 | 23 | @Override 24 | public synchronized void put(Key key, Value val) { 25 | buffer.put(key, val); 26 | } 27 | 28 | @Override 29 | public Value get(Key key) { 30 | return getSource().get(key); 31 | } 32 | 33 | @Override 34 | public synchronized boolean flushImpl() { 35 | if (!buffer.isEmpty()) { 36 | getBatchSource().updateBatch(buffer); 37 | buffer.clear(); 38 | return true; 39 | } else { 40 | return false; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/CachedSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import java.util.Collection; 4 | 5 | public interface CachedSource extends Source { 6 | 7 | 8 | Source getSource(); 9 | 10 | 11 | Collection getModified(); 12 | 13 | 14 | boolean hasModified(); 15 | 16 | 17 | long estimateCacheSize(); 18 | 19 | 20 | interface BytesKey extends CachedSource {} 21 | } 22 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/DbSettings.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public class DbSettings { 4 | 5 | public static final DbSettings DEFAULT = new DbSettings() 6 | .withMaxThreads(1) 7 | .withMaxOpenFiles(32); 8 | 9 | int maxOpenFiles; 10 | int maxThreads; 11 | 12 | private DbSettings() { 13 | } 14 | 15 | public static DbSettings newInstance() { 16 | DbSettings settings = new DbSettings(); 17 | settings.maxOpenFiles = DEFAULT.maxOpenFiles; 18 | settings.maxThreads = DEFAULT.maxThreads; 19 | return settings; 20 | } 21 | 22 | public int getMaxOpenFiles() { 23 | return maxOpenFiles; 24 | } 25 | 26 | public DbSettings withMaxOpenFiles(int maxOpenFiles) { 27 | this.maxOpenFiles = maxOpenFiles; 28 | return this; 29 | } 30 | 31 | public int getMaxThreads() { 32 | return maxThreads; 33 | } 34 | 35 | public DbSettings withMaxThreads(int maxThreads) { 36 | this.maxThreads = maxThreads; 37 | return this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/DbSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import java.util.Set; 4 | 5 | public interface DbSource extends BatchSource { 6 | 7 | void setName(String name); 8 | 9 | void open() throws RuntimeException; 10 | 11 | void open(DbSettings settings) throws RuntimeException; 12 | 13 | boolean isAlive(); 14 | 15 | void reset(); 16 | 17 | void close() throws Exception; 18 | 19 | V prefixLookup(byte[] key, int prefixBytes) throws RuntimeException; 20 | 21 | String getName(); 22 | 23 | Set keys() throws RuntimeException; 24 | } 25 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/HashedKeySource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public interface HashedKeySource extends Source { 4 | } 5 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/MemSizeEstimator.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public interface MemSizeEstimator { 4 | 5 | long estimateSize(E e); 6 | 7 | MemSizeEstimator ByteArrayEstimator = bytes -> { 8 | 9 | return bytes == null ? 0 : bytes.length + 16; 10 | }; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/MultiCache.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public abstract class MultiCache extends ReadWriteCache.BytesKey { 4 | 5 | public MultiCache(Source src) { 6 | super(src, WriteCache.CacheType.SIMPLE); 7 | } 8 | 9 | 10 | @Override 11 | public synchronized V get(byte[] key) { 12 | AbstractCachedSource.Entry ownCacheEntry = getCached(key); 13 | V ownCache = ownCacheEntry == null ? null : ownCacheEntry.value(); 14 | if (ownCache == null) { 15 | V v = getSource() != null ? super.get(key) : null; 16 | ownCache = create(key, v); 17 | put(key, ownCache); 18 | } 19 | return ownCache; 20 | } 21 | 22 | 23 | @Override 24 | public synchronized boolean flushImpl() { 25 | boolean ret = false; 26 | for (byte[] key: writeCache.getModified()) { 27 | V value = super.get(key); 28 | if (value == null) { 29 | 30 | ret |= flushChild(key, value); 31 | if (getSource() != null) { 32 | getSource().delete(key); 33 | } 34 | } else if (value.getSource() != null){ 35 | ret |= flushChild(key, value); 36 | } else { 37 | getSource().put(key, value); 38 | ret = true; 39 | } 40 | } 41 | return ret; 42 | } 43 | 44 | 45 | protected boolean flushChild(byte[] key, V childCache) { 46 | return childCache != null ? childCache.flush() : true; 47 | } 48 | 49 | 50 | protected abstract V create(byte[] key, V srcCache); 51 | } 52 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/NoDeleteSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public class NoDeleteSource extends AbstractChainedSource { 4 | 5 | public NoDeleteSource(Source src) { 6 | super(src); 7 | setFlushSource(true); 8 | } 9 | 10 | @Override 11 | public void delete(Key key) { 12 | } 13 | 14 | @Override 15 | public void put(Key key, Value val) { 16 | if (val != null) getSource().put(key, val); 17 | } 18 | 19 | @Override 20 | public Value get(Key key) { 21 | return getSource().get(key); 22 | } 23 | 24 | @Override 25 | protected boolean flushImpl() { 26 | return false; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/NodeKeyCompositor.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import org.platon.crypto.HashUtil; 4 | 5 | import static java.lang.System.arraycopy; 6 | 7 | public class NodeKeyCompositor implements SerializerIfc { 8 | 9 | public static final int HASH_LEN = 32; 10 | public static final int PREFIX_BYTES = 16; 11 | private byte[] addrHash; 12 | 13 | public NodeKeyCompositor(byte[] addrOrHash) { 14 | this.addrHash = addrHash(addrOrHash); 15 | } 16 | 17 | @Override 18 | public byte[] serialize(byte[] key) { 19 | return composeInner(key, addrHash); 20 | } 21 | 22 | @Override 23 | public byte[] deserialize(byte[] stream) { 24 | return stream; 25 | } 26 | 27 | public static byte[] compose(byte[] key, byte[] addrOrHash) { 28 | return composeInner(key, addrHash(addrOrHash)); 29 | } 30 | 31 | private static byte[] composeInner(byte[] key, byte[] addrHash) { 32 | 33 | validateKey(key); 34 | 35 | byte[] derivative = new byte[key.length]; 36 | arraycopy(key, 0, derivative, 0, PREFIX_BYTES); 37 | arraycopy(addrHash, 0, derivative, PREFIX_BYTES, PREFIX_BYTES); 38 | 39 | return derivative; 40 | } 41 | 42 | private static void validateKey(byte[] key) { 43 | if (key.length != HASH_LEN) 44 | throw new IllegalArgumentException("Key is not a hash code"); 45 | } 46 | 47 | private static byte[] addrHash(byte[] addrOrHash) { 48 | return addrOrHash.length == HASH_LEN ? addrOrHash : HashUtil.sha3(addrOrHash); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/PrefixLookupSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public class PrefixLookupSource implements Source { 4 | 5 | 6 | private int prefixBytes; 7 | private DbSource source; 8 | 9 | public PrefixLookupSource(DbSource source, int prefixBytes) { 10 | this.source = source; 11 | this.prefixBytes = prefixBytes; 12 | } 13 | 14 | @Override 15 | public V get(byte[] key) { 16 | return source.prefixLookup(key, prefixBytes); 17 | } 18 | 19 | @Override 20 | public void put(byte[] key, V val) { 21 | source.put(key, val); 22 | } 23 | 24 | @Override 25 | public void delete(byte[] key) { 26 | source.delete(key); 27 | } 28 | 29 | @Override 30 | public boolean flush() { 31 | return source.flush(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/SerializerIfc.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | public interface SerializerIfc { 4 | 5 | S serialize(T object); 6 | 7 | T deserialize(S stream); 8 | } 9 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/Source.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | 4 | public interface Source { 5 | 6 | 7 | void put(K key, V value); 8 | 9 | 10 | V get(K key); 11 | 12 | 13 | void delete(K key); 14 | 15 | 16 | boolean flush(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/SourceChainBox.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class SourceChainBox 7 | extends AbstractChainedSource { 8 | 9 | List chain = new ArrayList<>(); 10 | Source lastSource; 11 | 12 | public SourceChainBox(Source source) { 13 | super(source); 14 | } 15 | 16 | public void add(Source src) { 17 | chain.add(src); 18 | lastSource = src; 19 | } 20 | 21 | @Override 22 | public void put(Key key, Value val) { 23 | lastSource.put(key, val); 24 | } 25 | 26 | @Override 27 | public Value get(Key key) { 28 | return lastSource.get(key); 29 | } 30 | 31 | @Override 32 | public void delete(Key key) { 33 | lastSource.delete(key); 34 | } 35 | 36 | @Override 37 | protected boolean flushImpl() { 38 | return lastSource.flush(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/datasource/XorDataSource.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.datasource; 2 | 3 | import org.platon.common.utils.ByteUtil; 4 | 5 | public class XorDataSource extends AbstractChainedSource { 6 | 7 | private byte[] subKey; 8 | 9 | public XorDataSource(Source source, byte[] subKey) { 10 | super(source); 11 | this.subKey = subKey; 12 | } 13 | 14 | private byte[] convertKey(byte[] key) { 15 | return ByteUtil.xorAlignRight(key, subKey); 16 | } 17 | 18 | @Override 19 | public V get(byte[] key) { 20 | return getSource().get(convertKey(key)); 21 | } 22 | 23 | @Override 24 | public void put(byte[] key, V value) { 25 | getSource().put(convertKey(key), value); 26 | } 27 | 28 | @Override 29 | public void delete(byte[] key) { 30 | getSource().delete(convertKey(key)); 31 | } 32 | 33 | @Override 34 | protected boolean flushImpl() { 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/enums/OverlimitStrategyEnum.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.enums; 2 | 3 | public enum OverlimitStrategyEnum { 4 | 5 | OVERLIMIT_STRATEGY_COMMIT(1,"超限策略-提交"), 6 | OVERLIMIT_STRATEGY_THROW_EXCEPTION(2,"超限策略-报错"); 7 | 8 | private String name; 9 | private int code; 10 | 11 | private OverlimitStrategyEnum(int code, String name){ 12 | this.name = name; 13 | this.code = code; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public int getCode() { 25 | return code; 26 | } 27 | 28 | public void setCode(int code) { 29 | this.code = code; 30 | } 31 | 32 | public static String getNameByCodeValue(int code){ 33 | OverlimitStrategyEnum[] allEnums = values(); 34 | for(OverlimitStrategyEnum enableStatus : allEnums){ 35 | if(enableStatus.getCode()==code){ 36 | return enableStatus.getName(); 37 | } 38 | } 39 | return null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/exception/OverlimitException.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.exception; 2 | 3 | 4 | public class OverlimitException extends RuntimeException{ 5 | 6 | public OverlimitException(String message){ 7 | super(message); 8 | } 9 | 10 | public OverlimitException(String message, Throwable cause) { 11 | super(message, cause); 12 | } 13 | 14 | public OverlimitException(Throwable cause) { 15 | super(cause); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/trie/SecureTrie.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.trie; 2 | 3 | import org.platon.storage.datasource.Source; 4 | 5 | import static org.platon.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; 6 | import static org.platon.crypto.HashUtil.sha3; 7 | 8 | public class SecureTrie extends TrieImpl { 9 | 10 | public SecureTrie(Source cache) { 11 | super(cache, true, 32); 12 | } 13 | 14 | public SecureTrie(Source cache, byte[] root) { 15 | super(cache, true, 32, root); 16 | } 17 | 18 | public SecureTrie(){} 19 | 20 | @Override 21 | public byte[] get(byte[] key) { 22 | return super.get(sha3(key)); 23 | } 24 | 25 | @Override 26 | public void put(byte[] key, byte[] value) { 27 | super.put(sha3(key), value); 28 | } 29 | 30 | @Override 31 | public void delete(byte[] key) { 32 | put(key, EMPTY_BYTE_ARRAY); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/trie/Trie.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.trie; 2 | 3 | import org.platon.storage.datasource.Source; 4 | 5 | public interface Trie extends Source { 6 | 7 | byte[] getRootHash(); 8 | 9 | void setRoot(byte[] root); 10 | 11 | void clear(); 12 | } 13 | -------------------------------------------------------------------------------- /storage/src/main/java/org.platon.storage/utils/AutoLock.java: -------------------------------------------------------------------------------- 1 | package org.platon.storage.utils; 2 | 3 | import java.util.concurrent.locks.Lock; 4 | 5 | public final class AutoLock implements AutoCloseable { 6 | 7 | private final Lock lock; 8 | 9 | public AutoLock(Lock l) { 10 | this.lock = l; 11 | } 12 | 13 | public final AutoLock lock() { 14 | this.lock.lock(); 15 | return this; 16 | } 17 | 18 | public final void close() { 19 | this.lock.unlock(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /storage/src/test/resources/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /storage/src/test/resources/config/system.properties: -------------------------------------------------------------------------------- 1 | leveldbPath=C:\\sunzone\\leveldb 2 | rocksdbPath=C:\\sunzone\\rocksdb -------------------------------------------------------------------------------- /storage/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg %n 7 | 8 | 9 | DEBUG 10 | 11 | 12 | 13 | 14 | ../logs/storage_test.log 15 | 16 | ../logs/storage_test_%d{yyyy-MM-dd}.log 17 | 30 18 | 19 | 20 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /tests/build.gradle: -------------------------------------------------------------------------------- 1 | sourceCompatibility = 1.8 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | testCompile group: 'junit', name: 'junit', version: '4.11' 9 | } 10 | -------------------------------------------------------------------------------- /vm/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | sourceCompatibility = 1.8 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | testCompile group: 'junit', name: 'junit', version: '4.11' 10 | } 11 | --------------------------------------------------------------------------------