| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.tuweni.devp2p.eth |
| |
| import org.apache.tuweni.bytes.Bytes |
| import org.apache.tuweni.eth.Hash |
| import org.apache.tuweni.units.bigints.UInt256 |
| import org.apache.tuweni.units.bigints.UInt64 |
| import java.util.zip.CRC32 |
| |
| /** |
| * Blockchain information to be shared over the network with peers |
| */ |
| interface BlockchainInformation { |
| /** |
| * Our network ID. 1 for mainnet. |
| * @return our network ID |
| */ |
| fun networkID(): UInt256 |
| |
| /** |
| * Total difficulty of our canonical chain |
| * @return our best block total difficulty |
| */ |
| fun totalDifficulty(): UInt256 |
| |
| /** |
| * Best block hash we know |
| * @return our best block hash from our chain |
| */ |
| fun bestHash(): Hash |
| |
| /** |
| * Best block number we know |
| * |
| * @return our best block number from our chain |
| */ |
| fun bestNumber(): UInt256 |
| |
| /** |
| * Genesis block hash |
| * |
| * @return the genesis block hash |
| */ |
| fun genesisHash(): Hash |
| |
| /** |
| * Forks of our network we know |
| * |
| * @param all fork block numbers |
| */ |
| fun forks(): List<Long> |
| |
| /** |
| * Get all our fork hashes |
| * |
| * @param all fork hashes, sorted |
| */ |
| fun getForkHashes(): List<Bytes> { |
| val crc = CRC32() |
| crc.update(genesisHash().toArrayUnsafe()) |
| val forkHashes = ArrayList<Bytes>(listOf(Bytes.ofUnsignedInt(crc.value))) |
| for (fork in forks()) { |
| val byteRepresentationFork = UInt64.valueOf(fork).toBytes() |
| crc.update(byteRepresentationFork.toArrayUnsafe(), 0, byteRepresentationFork.size()) |
| forkHashes.add(Bytes.ofUnsignedInt(crc.value)) |
| } |
| return forkHashes |
| } |
| |
| fun getLastestApplicableFork(number: Long): ForkInfo |
| } |
| |
| data class ForkInfo(val next: Long, val hash: Bytes) |
| |
| /** |
| * POJO - constant representation of the blockchain information |
| * |
| * @param networkID the network ID |
| * @param totalDifficulty the total difficulty of the chain |
| * @param bestHash best known hash |
| * @param bestNumber best known number |
| * @param genesisHash the genesis block hash |
| * @param forks known forks |
| */ |
| class SimpleBlockchainInformation( |
| val networkID: UInt256, |
| val totalDifficulty: UInt256, |
| val bestHash: Hash, |
| val bestNumber: UInt256, |
| val genesisHash: Hash, |
| possibleForks: List<Long>, |
| ) : BlockchainInformation { |
| |
| private val forkIds: List<ForkInfo> |
| private val forks: List<Long> |
| |
| init { |
| this.forks = possibleForks.filter { it > 0 }.sorted().distinct() |
| val crc = CRC32() |
| crc.update(genesisHash.toArrayUnsafe()) |
| val genesisHashCrc = Bytes.ofUnsignedInt(crc.value) |
| val forkHashes = mutableListOf(genesisHashCrc) |
| for (f in forks) { |
| val byteRepresentationFork = Bytes.ofUnsignedLong(f).toArrayUnsafe() |
| crc.update(byteRepresentationFork, 0, byteRepresentationFork.size) |
| forkHashes.add(Bytes.ofUnsignedInt(crc.value)) |
| } |
| val mutableForkIds = mutableListOf<ForkInfo>() |
| |
| // This loop is for all the fork hashes that have an associated "next fork" |
| for (i in forks.indices) { |
| mutableForkIds.add(ForkInfo(forks.get(i), forkHashes[i])) |
| } |
| if (forks.isNotEmpty()) { |
| mutableForkIds.add(ForkInfo(0, forkHashes.last())) |
| } |
| this.forkIds = mutableForkIds.toList() |
| } |
| |
| override fun networkID(): UInt256 = networkID |
| |
| override fun totalDifficulty(): UInt256 = totalDifficulty |
| |
| override fun bestHash(): Hash = bestHash |
| |
| override fun bestNumber(): UInt256 = bestNumber |
| |
| override fun genesisHash(): Hash = genesisHash |
| |
| override fun forks(): List<Long> = forks |
| |
| override fun getLastestApplicableFork(number: Long): ForkInfo { |
| for (fork in forkIds) { |
| if (number < fork.next) { |
| return fork |
| } |
| } |
| return forkIds.last() |
| } |
| } |