diff --git a/doc/protocol.md b/doc/protocol.md index 5cf1e8b9..f5add393 100644 --- a/doc/protocol.md +++ b/doc/protocol.md @@ -24,7 +24,7 @@ If an outgoing connection to a verified peer is rejected, the peer loses the ver If an outgoing connection to a non-verified peer is rejected, the peer is removed from the list of peers. If an outgoing connection to a non-verified peer is accepted and an `ExchangePublicPeers` message is received, the peer gets the verified status. If a protocol violation is detected at any moment during communication (allowing to assume the remote end runs something else, not Qubic node), then the IP is removed even if it is verified. -An IP is only removed from the list of peers if the list still has at least 10 entries afterwards. +An IP is only removed from the list of peers if the list still has at least 10 entries afterwards and if it is not in the initial `knownPublicPeers`. ## ... diff --git a/src/Qubic.vcxproj b/src/Qubic.vcxproj index f700266a..a0053d07 100644 --- a/src/Qubic.vcxproj +++ b/src/Qubic.vcxproj @@ -29,6 +29,7 @@ + diff --git a/src/Qubic.vcxproj.filters b/src/Qubic.vcxproj.filters index d851300d..853d91e1 100644 --- a/src/Qubic.vcxproj.filters +++ b/src/Qubic.vcxproj.filters @@ -105,6 +105,9 @@ network_core + + network_messages + diff --git a/src/network_core/peers.h b/src/network_core/peers.h index 30e98872..6ac9d6c2 100644 --- a/src/network_core/peers.h +++ b/src/network_core/peers.h @@ -242,10 +242,54 @@ static void enqueueResponse(Peer* peer, unsigned int dataSize, unsigned char typ RELEASE(responseQueueHeadLock); } +/** +* checks if a given address is a bogon address +* a bogon address is an ip address which should not be used pubicly (e.g. private networks) +* +* @param address the ip address to be checked +* @return true if address is bogon or false if not +*/ +static bool isBogonAddress(const IPv4Address& address) +{ + return (!address.u8[0]) + || (address.u8[0] == 127) + || (address.u8[0] == 10) + || (address.u8[0] == 172 && address.u8[1] >= 16 && address.u8[1] <= 31) + || (address.u8[0] == 192 && address.u8[1] == 168) + || (address.u8[0] == 255); +} + +/** +* checks if a given address was manually set in the initial list of known public peers +* +* @param address the ip address to be checked +* @return true if the ip address is in the Known Public Peers or false if not +*/ +static bool isAddressInKnownPublicPeers(const IPv4Address& address) +{ + // keep this exception to avoid bogon addresses kept for outgoing connections + if (isBogonAddress(address)) + return false; + + for (unsigned int i = 0; i < sizeof(knownPublicPeers) / sizeof(knownPublicPeers[0]); i++) + { + const IPv4Address& peer_ip = *reinterpret_cast(knownPublicPeers[i]); + if (peer_ip == address) + return true; + } + return false; +} + // Forget public peer (no matter if verified or not) if we have more than the minium number of peers static void forgetPublicPeer(const IPv4Address& address) { + // if address is one of our initial peers we don't forget it + if (isAddressInKnownPublicPeers(address)) + { + return; + } + if (listOfPeersIsStatic) { return; @@ -300,14 +344,10 @@ static void penalizePublicPeerRejectedConnection(const IPv4Address& address) } } + static void addPublicPeer(const IPv4Address& address) { - if ((!address.u8[0]) - || (address.u8[0] == 127) - || (address.u8[0] == 10) - || (address.u8[0] == 172 && address.u8[1] >= 16 && address.u8[1] <= 31) - || (address.u8[0] == 192 && address.u8[1] == 168) - || (address.u8[0] == 255)) + if (isBogonAddress(address)) { return; } diff --git a/src/network_messages/all.h b/src/network_messages/all.h index 9a94a848..1343e881 100644 --- a/src/network_messages/all.h +++ b/src/network_messages/all.h @@ -13,3 +13,4 @@ #include "special_command.h" #include "tick.h" #include "transactions.h" +#include "system_info.h" diff --git a/src/network_messages/system_info.h b/src/network_messages/system_info.h new file mode 100644 index 00000000..9588c1d7 --- /dev/null +++ b/src/network_messages/system_info.h @@ -0,0 +1,32 @@ +#pragma once + +#include "common_def.h" + +#define REQUEST_SYSTEM_INFO 46 + + +#define RESPOND_SYSTEM_INFO 47 + +struct RespondSystemInfo +{ + short version; + unsigned short epoch; + unsigned int tick; + unsigned int initialTick; + unsigned int latestCreatedTick; + + unsigned short initialMillisecond; + unsigned char initialSecond; + unsigned char initialMinute; + unsigned char initialHour; + unsigned char initialDay; + unsigned char initialMonth; + unsigned char initialYear; + + unsigned int numberOfEntities; + unsigned int numberOfTransactions; + + m256i randomMiningSeed; +}; + +static_assert(sizeof(RespondSystemInfo) == 2 + 2 + 4 + 4 + 4 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 4 + 32 + 4, "Something is wrong with the struct size of RespondSystemInfo."); diff --git a/src/public_settings.h b/src/public_settings.h index 2f040e24..79d5e888 100644 --- a/src/public_settings.h +++ b/src/public_settings.h @@ -8,11 +8,11 @@ #define NUMBER_OF_SOLUTION_PROCESSORS 2 // do not increase this for this epoch, because there may be issues due too fast ticking #define VERSION_A 1 -#define VERSION_B 191 +#define VERSION_B 192 #define VERSION_C 0 -#define EPOCH 94 -#define TICK 12270000 +#define EPOCH 95 +#define TICK 12380000 // random seed is now obtained from spectrumDigests @@ -30,7 +30,7 @@ static unsigned short CONTRACT_FILE_NAME[] = L"contract????.???"; #define NUMBER_OF_OUTPUT_NEURONS 2400 #define MAX_INPUT_DURATION 200 #define MAX_OUTPUT_DURATION 200 -#define SOLUTION_THRESHOLD_DEFAULT 693 +#define SOLUTION_THRESHOLD_DEFAULT 694 #define USE_SCORE_CACHE 1 #define SCORE_CACHE_SIZE 1000000 // the larger the better #define SCORE_CACHE_COLLISION_RETRIES 20 // number of retries to find entry in cache in case of hash collision diff --git a/src/qubic.cpp b/src/qubic.cpp index b2f4e92e..5ac13b8d 100644 --- a/src/qubic.cpp +++ b/src/qubic.cpp @@ -1020,6 +1020,32 @@ static void processRequestContractFunction(Peer* peer, const unsigned long long } } +static void processRequestSystemInfo(Peer* peer, RequestResponseHeader* header) +{ + RespondSystemInfo respondedSystemInfo; + + respondedSystemInfo.version = system.version; + respondedSystemInfo.epoch = system.epoch; + respondedSystemInfo.tick = system.tick; + respondedSystemInfo.initialTick = system.initialTick; + respondedSystemInfo.latestCreatedTick = system.latestLedTick; + + respondedSystemInfo.initialMillisecond = system.initialMillisecond; + respondedSystemInfo.initialSecond = system.initialSecond; + respondedSystemInfo.initialMinute = system.initialMinute; + respondedSystemInfo.initialHour = system.initialHour; + respondedSystemInfo.initialDay = system.initialDay; + respondedSystemInfo.initialMonth = system.initialMonth; + respondedSystemInfo.initialYear = system.initialYear; + + respondedSystemInfo.numberOfEntities = numberOfEntities; + respondedSystemInfo.numberOfTransactions = numberOfTransactions; + + respondedSystemInfo.randomMiningSeed = score->initialRandomSeed; + + enqueueResponse(peer, sizeof(respondedSystemInfo), RESPOND_SYSTEM_INFO, header->dejavu(), &respondedSystemInfo); +} + static void processSpecialCommand(Peer* peer, RequestResponseHeader* header) { SpecialCommand* request = header->getPayload(); @@ -1281,6 +1307,12 @@ static void requestProcessor(void* ProcedureArgument) } break; + case REQUEST_SYSTEM_INFO: + { + processRequestSystemInfo(peer, header); + } + break; + case SpecialCommand::type: { processSpecialCommand(peer, header); diff --git a/src/score.h b/src/score.h index e408cf32..9c65af09 100644 --- a/src/score.h +++ b/src/score.h @@ -22,6 +22,7 @@ template< struct ScoreFunction { int miningData[dataLength]; + m256i initialRandomSeed; #pragma warning(push) #pragma warning(disable:4293) @@ -71,6 +72,7 @@ struct ScoreFunction void initMiningData(m256i randomSeed) { + initialRandomSeed = randomSeed; // persist the initial random seed to be able to sned it back on system info response random((unsigned char*)&randomSeed, (unsigned char*)&randomSeed, (unsigned char*)miningData, sizeof(miningData)); } diff --git a/src/smart_contracts/README.md b/src/smart_contracts/README.md index a7dc8c89..67ead9d1 100644 --- a/src/smart_contracts/README.md +++ b/src/smart_contracts/README.md @@ -1,8 +1,24 @@ -# smart_contracts +# Qubic Contract Development Guidelines This directory contains the smart contract implementations in header files starting with a capital letter. -Further, it contain `qpi.h`, the Qubic Programming Interface for implementing the smart contracts. +Further, it contains `qpi.h`, the Qubic Programming Interface for implementing the smart contracts. It is available automatically in the smart contract implementation header files. -Other header files with starting with a lower case letter, such as `math_lib.h`, provide additional library functions that may be used in the smart contract implementation header files (for example, use `#include "math_lib.h"`). +Other header files starting with a lowercase letter, such as `math_lib.h`, provide examples of useful functions that can be used in contract code. + +This document outlines the guidelines for developing secure and efficient Qubic contracts. Adherence to these guidelines is crucial for ensuring the proper functionality and security of your contracts within the Qubic environment. + +### Syntax and Formatting: +- Qubic contracts generally inherit the syntax and format of C/C++. +- However, due to security reasons, certain things are prohibited: + - Declaring and accessing arrays using the C/C++ notation (`[` `]`). Utilize pre-defined array structures within qpi.h such as `collection`, `uint32_64`, `uint32_128`,... + - Any pointer-related techniques such as casting, accessing,... + - Native data types like `int`, `long`, `char`,... Use their corresponding predefined datatypes in `qpi.h` (`int8`, `int16`, `int32`, `int64`,...) + - Inclusion of other files via `#include`. All functions must reside within a single file. + - Math operators `%` and `/`. Use `mod` and `div` from `qpi.h` instead. `+`, `-`, `*`(multiplication), and bit-wise operators are accepted. + - Local variable declaration, even for for-loop. You need to define all necessary variables in the contract state and utilize them. + - The `typedef`, `union` keyword. + - Floating points datatypes (half, float, double) + +Currently, the maximum contract state size is capped at 1 GiB (03/02/2024). This value is subject to change based on hardware upgrades of computors.