Commit Graph
77 Commits
Author SHA1 Message Date
dcrubro 4d39614cb5 Fix all ThreadSanitizer-reported races in the node lifecycle (8 reports -> 0)
Found by running two nodes under -fsanitize=thread through connect -> mine -> broadcast -> clean
exit. None are in consensus code; all are connection setup/teardown.

Stop flags were plain or volatile ints written by one thread and read as a loop condition by
another. volatile stops the compiler hoisting the load but provides neither atomicity nor
ordering, which on arm64 is a real visibility gap, not just a sanitizer complaint. Now _Atomic:
 - net_node_t.maintenanceRunning  (Node_Destroy vs Node_MaintenanceThread)
 - tcp_server_t.isRunning         (TcpServer_Stop vs both accept threads) -- was a bare int, so
                                   the accept loop could legally be hoisted and never see the stop
 - udp_node_t.isRunning           (UdpNode_Stop vs the recv and retry threads)

TcpServer_Stop had a use-after-free, not merely a race: it took clientsMutex only long enough to
read the array pointer, then walked the slots unlocked. An exiting client thread clears its own
slot under that mutex and immediately destroys and frees the connection, so Stop could
RequestClose and pthread_join a freed pointer on any shutdown with an active peer.
 - Stop now requests the close and copies each pthread_t under the mutex, then joins from the
   copied handles, so the connection is never dereferenced outside the lock
 - the client thread's TcpConnection_Destroy/free moved inside the same critical section, which
   closes the window entirely

Client threads that disconnected normally were never joined and leaked their thread resources:
Stop only joins clients still present in the array, and a normal exit removes itself first. Stop
now claims each slot as it copies the handle, so the client thread can tell who owns its join --
it detaches itself if it successfully removed its own slot, and stays joinable if Stop already
claimed it. Both decisions happen under clientsMutex so the cases cannot interleave.

Node_Destroy cleared outbound slots with no lock (via TcpClient_Disconnect) while live inbound
client threads read the same field correctly under outboundLock in Node_HasLiveConnectionTo. The
lock cannot just be held across the destroy, because that path joins an io thread whose
on_disconnect callback takes outboundLock itself. Reworked to detach the connections from their
slots under the lock and tear them down outside it -- the pattern Node_ReapDeadOutbound already
uses in this file. This one only surfaced once the other five were fixed.

Verified: TSan clean over the same run; nodes still converge (height 25, identical tip); shallow
fork still adopts, depth-8 fork still defers on the reorg penalty, and the forced-orphan
regression still reaches full height with zero coinbase rejections.
2026-07-28 23:07:57 +02:00
dcrubro 42b325d57a Fix self-deadlock on chainLock and fix double-delivery of accepted blocks (+ DUPLICATE enum entry) 2026-07-28 17:22:48 +02:00
dcrubro 1ff2890c0f Fix the reorg system: make rollback survivable, adopt by cumulative work, and enforce the reorg penalty everywhere
(This is a big one, get ready - I told Claude to write the commit message cause I couldn't be bothered)

Root cause: reorg was broken at every layer and the failures compounded. Verified with the node's own
SKALACOIN_FORCE_ORPHAN_REORG debug mode, which stalled permanently at height 2 on 114 consecutive
coinbase-validation failures. A binary built at HEAD behaves identically, so none of this is a regression —
the reorg path had simply never worked.

Rollback (the keystone):
 - Chain_RollbackToHeight always returned false on any node that had ever saved or loaded its chain, and
   only after it had already truncated the chain and destroyed the balance sheet. Chain_RecomputeRuntimeState
   bails on any header-only block, and Chain_SaveToFile nulls transactions on every in-memory block once
   persisted, so the failure was universal in practice. Both callers treated the false as "nothing happened"
 - Added Chain_BorrowBlockTransactions / Chain_ReturnBlockTransactions, which fall back to the on-disk copy
   when the in-memory block has been compacted to headers
 - Supply is now accumulated in the rollback's existing balance-sheet replay pass instead of a second
   Chain_RecomputeRuntimeState pass
 - Gave Chain_RecomputeRuntimeState the same disk fallback: it had been failing on every restart with an
   existing chain, silently leaving currentSupply/currentReward at whatever came out of chain.meta

Fork choice is now cumulative work, not height:
 - Added Chain_ComputeBlockWork / Chain_ComputeWorkRange / Chain_ComputeBranchWork, computing
   2^256 / (target + 1) per block and summing over a range. Derived on demand from headers — no header,
   chain.meta or wire-format change
 - uint256 only had add/sub/cmp, so added uint256_divide (restoring binary long division),
   uint256_from_be_bytes, uint256_bitwise_not and uint256_is_zero
 - Comparison is strictly greater, so tied tips do not cause two nodes to keep swapping
 - Height-based choice was wrong now that difficulty actually varies: a long low-difficulty branch beat a
   short high-difficulty one

Atomic branch replacement:
 - Added Chain_ReplaceBranch: validate linkage, apply the reorg penalty, compare work, snapshot the outgoing
   blocks, roll back, apply. On any failure the original chain, balance sheet, supply, reward and difficulty
   target are restored. The caller keeps ownership of its blocks in every case — the chain applies copies
 - Split Chain_AddBlock and Chain_RollbackToHeight into locked public wrappers over unlocked internals, so a
   whole branch swap happens under one lock acquisition and Chain_OnTipAdvanced runs once per reorg rather
   than once per block
 - Chain_AddBlock now validates header.prevHash against the tip. It never did — that check lived only in
   Chain_IsValid and the network path, which is exactly why a rollback-then-reapply could splice blocks from
   two different forks into a chain that no longer links up
 - Moved the currentSupply/currentReward update into Chain_AddBlock. Each caller used to do it separately, so
   the orphan-attach and maintenance-thread paths never did, and the next block's coinbase was then validated
   against a stale currentReward and rejected forever. This was the height-2 stall

Reorg penalty (Horizen-style delayed block submission):
 - The penalty was only ever reachable from the manual sync command. The P2P broadcast -> orphan pool ->
   branch adoption path, which is the path an attacker actually uses, had none at all and picked the winner
   by raw height. It is now enforced inside Chain_ReplaceBranch, the single choke point every adoption
   passes through
 - Removed its application to the sync fetch window. The height gap to a peer is not a reorg depth;
   penalising it only throttled honest catch-up, and for gaps of 4-50 it collapsed the window to one block
   per pass, defeating MAX_PARALLEL_FETCHES
 - The depth is stamped once when a branch is first observed (orphan_entry_t.observedAtTipHeight) and never
   recomputed. Re-deriving it from a moving tip never converges: depth and elapsed both grow by one per block
   while penalty(depth) grows faster, so a penalized branch could never be adopted at all
 - The initial-sync exemption now comes from Chain_IsInitialBlockDownload, which uses the local median time
   past over MEDIAN_TIME_SPAN blocks. It used to key off the peer's advertised height, so any peer claiming
   localHeight + INITIAL_SYNC_HEIGHT_DIFF could switch reorg handling off for the whole session. A median
   rather than the tip alone means one backdated block cannot fake it either

Orphan pool (largely rewritten):
 - Added a pool mutex. It had no synchronisation whatsoever while being mutated from the 1 Hz maintenance
   thread, every per-peer TCP thread and the REPL thread; a concurrent insert could realloc the array while a
   scan held a raw element pointer. The lock is never held across a call into chain.c
 - Dedup by block hash, a MAX_ORPHAN_BLOCKS cap with oldest-first eviction, and pruning of entries that can
   no longer apply. Nothing was ever reaped before, and orphans are reachable before the chain-derived
   difficulty check, so this is also the memory-exhaustion fix
 - Candidate branches are now assembled by following prevHash from the fork point. Taking the first orphan
   found at each successive height could interleave blocks from two competing forks into one incoherent branch
 - Fixed rollbackHeight = forkHeight - 1. Chain_RollbackToHeight is exclusive, so every non-genesis adoption
   amputated one block too many and then failed Chain_AddBlock's index check
 - Fixed a block_t wrapper leak on every successful attach (free the wrapper, not Block_Destroy — the chain
   owns the transactions after a shallow copy)
 - Permanently invalid orphans are dropped instead of being retried on every maintenance tick forever

Forks below the tip are now discoverable:
 - A block at blockNumber < chainSize was rejected and freed, so the fork point and the lower half of any
   competing branch were always thrown away and a sub-tip fork could never be learned. Now the hash is
   compared: identical means a duplicate and is ignored, different means it goes to the orphan pool
 - The sync loop probes downwards (RequestForkWindow, bounded by REORG_FETCH_DEPTH and MAX_FORK_PROBE_ROUNDS)
   when it makes no progress while the peer is ahead. That is the only trigger that fires for a genuine
   sub-tip fork, because the old divergence check could only see blocks that had already entered our chain.
   FETCH_BLOCK already answers from the peer's own chain, so no protocol change was needed
 - Removed the rollback-to-height-0 path. "Could not find the parent" used to wipe the entire local chain,
   genesis included, and any peer could trigger it with a single unlinked block

Floating point removed from consensus and network math:
 - Chain_ComputeTargetAtHeight (the difficulty retarget) used double ratio arithmetic, and
   FetchScheduler_ComputeReorgPenaltyBlocks used double/pow/ceil. Both are consensus-critical and are now
   integer only; float results are not reproducible across platforms and compilers, and a single last-digit
   difference in a target or a penalty splits the network
 - The penalty constants became integer rationals (REORG_PENALTY_FACTOR_NUM/DEN, integer EXPONENT and
   REF_BLOCK_TIME) with saturating exponentiation and explicit ceiling division. Output is unchanged:
   penalty(4)=10, penalty(8)=39, penalty(10)=60, penalty(50)=1500, penalty(100)=6000
 - Removed the unused float macros DAG_MAX_UP/DOWN_SWING_PERCENTAGE and the now-dead math.h include from
   constants.h. Both were latent: DAG size feeds PoW verification. Replaced with integer numerator/denominator
   constants and used them at both clamp sites (values verified identical)

Other fixes that were blocking fork propagation:
 - madeProgressOverall was set but never reset, so after one productive pass the "no progress -> stop" guard
   could never fire again and the sync loop could spin forever holding the REPL
 - seenBlocks was inserted before/regardless of a successful send, so a block broadcast while no peer was
   connected was never offered again. It is now recorded only after the block actually goes out
 - Broadcasts relayed to outbound connections only, so in a two-node setup the dialled node never pushed
   anything back and the dialer learned of new blocks only via a manual sync. Inbound peers are now relayed to

Verified with two-node harnesses at a shortened adjustment interval:
 - forced-orphan regression: was height 2 with 114 coinbase rejections, now reaches the peer's height with
   zero rejections and both nodes report Chain OK
 - sub-tip fork at depth 3: the node discovers the fork below its own tip, discards its three blocks, adopts
   the heavier five, and both nodes converge on an identical tip hash
 - deep fork at depth 8: the strictly heavier branch is correctly refused with depth=8 penalty=39 elapsed=0
 - uint256 work arithmetic covered by a standalone test (division, big-endian conversion, monotonicity,
   halved target doubles work)

One issue found along the way: the chain in build/chain_data does not pass fullverify. Block 7683 reverts to
INITIAL_DIFFICULTY where it should carry 0x1f06df14, i.e. it contains blocks mined before 1288a64 landed. A
binary built at HEAD rejects it too, so this is stale data rather than a regression — it needs a wipechain
and a re-mine.
2026-07-28 00:24:45 +02:00
dcrubro 1288a64977 Fixed the target computation to trigger on syncs - old system would cause difficulty mismatches on syncs, reorgs, etc. 2026-07-27 19:21:39 +02:00
dcrubro c16b88fc5a Add timestamp field to transactions - allows multiple transactions with the same Ins/Outs 2026-07-27 14:34:30 +02:00
dcrubro f9c785b316 Add timestamp field to transactions - allows multiple transactions with the same Ins/Outs 2026-07-27 14:30:06 +02:00
dcrubro 0e90f7d5db Fix multi-homed / IPv6 peer identity: nodes adding themselves and reconnect churn
Root cause: peers were keyed only by (IP, listen port). An IPv6 host holds several addresses at once, so one node appeared as several peers and could not recognise its own addresses.

Protocol:
 - Added a random per-run node identity (localNodeId), advertised as a length-guarded trailing field in HELLO and ACK_HELLO — backwards compatible with peers that omit it
 - Added peerNodeId to tcp_connection_t; peers are now identified by this rather than by an endpoint
 - ACK_HELLO is now sent before any decision to drop the connection, so a rejected dialer learns whose address it reached instead of retrying forever

Self-connection:
 - Identity match → close the connection and record that endpoint permanently as our own
 - Self-endpoint set preemptively seeded from getifaddrs() at startup, so a node knows its own addresses before ever dialing one
 - Node_ConnectPeer refuses self endpoints, which also kills the echo-back chain that could exhaust connection slots

Duplicate connections and churn:
 - Dedup by identity per direction — one inbound and one outbound per physical peer, regardless of how many addresses it has
 - Moved dial history out of the peer table, so striking a peer no longer resets its connect-retry cooldown (this was the loop engine: strike → re-learn via gossip → redial next tick)
 - Node_HasOtherInboundFrom / Node_HasLiveConnectionTo now ignore connections that are already tearing down, and match on identity as well as endpoint

Gossip hygiene:
 - Never hand a peer its own other addresses in a PEERS reply (matched on identity, not just the socket address)
 - Reject unusable endpoints: link-local without scope id, unspecified, multicast, site-local (loopback stays allowed for local testing)
 - Normalise IPv4-mapped IPv6 so one host cannot occupy two entries

Two bugs found along the way:
 - All nodes drew the same identity — random_eight_byte() comes from srand(time(NULL)), so processes started in the same second produced identical values. Added random_secure_eight_byte() (/dev/urandom) for the identity, and mixed the pid into the seed so connection IDs stop colliding too
 - Identity dedup initially left inbound-only nodes mute — broadcasts traverse outbound connections only, so suppressing a dial-back because an inbound existed would have silenced such a node. Corrected to per-direction

Other:
 - peers output now shows each entry's node identity and the node's own endpoints
 - Added _DEFAULT_SOURCE to the build so getifaddrs() stays visible on glibc
2026-07-27 14:08:57 +02:00
dcrubro 5aa99ecb01 Change functions IsValidIPv4/v6 to use addrinfo instead of custom logic 2026-07-27 12:31:03 +02:00
dcrubro 3e5c051645 Change functions IsValidIPv4/v6 to use addrinfo instead of custom logic 2026-07-27 12:28:34 +02:00
dcrubro c4e28df46f Fix txpooldetail command not working, add missing commands to list, fix connect command for ipv6 2026-07-27 12:22:43 +02:00
dcrubro 88a9caa46c Reap dead outbound connection slots; strike disconnected peers from discovery. Two related connection-lifecycle fixes on top of the SIGPIPE fix.
Reclaim outbound slots on peer disconnect:
- TcpClient_ThreadProc fired on_disconnect but never cleared the outbound
  slot, closed the fd, joined the io thread, or freed the connection, so a
  dead peer permanently held its outboundClients[] slot. After MAX_CONS (32)
  churned connections the node could make no new outbound connections, and
  leaked fds/threads/memory. (The inbound side already self-reclaimed.)
- Add a reaper (Node_ReapDeadOutbound) on the maintenance thread: under
  outboundLock it detaches dead (disconnect-notified) slots, then joins the
  io thread and destroys/frees each connection outside the lock.
- Guard against use-after-free with a pin count on tcp_connection_t
  (TcpConnection_Pin/Unpin). The only cross-thread consumer holding a raw
  connection pointer across a blocking op is the `sync` command (via
  Node_GetBestOutboundPeer); it now pins the peer and unpins when done, and
  the reaper skips pinned connections. Discovery's snapshots run on the
  reaper's own thread, so they need no pin.
- Node_GetBestOutboundPeer/GetClientList/GetPeerEndpoints skip
  disconnect-notified connections so a dead peer is never handed out.
- Node_Destroy stops+joins the maintenance thread before tearing down
  outbound clients, so the reaper can't race shutdown.

Strike disconnected peers from the discovery peer list:
- Add NodeDiscovery_RemovePeer + Node_HandlePeerDisconnect: on disconnect,
  remove the peer from the known-peer table once no live connection (inbound
  or outbound) to its listen endpoint remains (Node_HasLiveConnectionTo;
  disconnect-notified conns don't count, so both directions dropping at once
  is handled). Wired into Node_Server_OnDisconnect and Node_Client_OnDisconnect.
2026-07-26 23:08:21 +02:00
dcrubro f9e3f8cbbb SIGPIPE fix - don't terminate on nodes being nodes 2026-07-23 14:23:38 +02:00
dcrubro 4417095ab5 force one inbound and one outbound between two nodes 2026-07-23 14:00:04 +02:00
dcrubro 21fe73fb01 Add NodeDiscovery: multi-hop peer crawl with UDP-ping preference
- Implement NodeDiscovery engine: known-peer table (DynArr) with a
  per-tick seed/ping/query/connect state machine driven by the node
  maintenance thread; bounded multi-hop crawl (FANOUT peers per node,
  hop-capped) that connects to reachable peers lowest-ping-first
- Add GET_PEERS/PEERS TCP opcodes for peer-list exchange, handled on
  both inbound and outbound connections
- Measure UDP round-trip time and pass it to the on_pong callback
  (previously the send timestamp was only used for retries)
- Advertise each node's listen port in HELLO/ACK_HELLO and store it
  per-connection, so inbound-only peers and non-default ports are
  discoverable (length-guarded parse; wire-compatible with old peers)
- Wire a udp_node_t + node_discovery_t into net_node_t: init/start in
  Node_Create, tick in the maintenance loop, teardown in Node_Destroy
  (stop UDP before destroying discovery to avoid callback races)
- Add Node_ConnListenEndpoint / Node_GetPeerEndpoints helpers to derive
  peers' listen endpoints (outbound: dialed port; inbound: advertised),
  with IPv4-mapped-IPv6 normalization and IP+port dedup
- Match ping pong/timeout callbacks by peer address (the UDP layer owns
  the nonce), fixing discovered peers stuck UNREACHABLE
- Ping the peer's listen port instead of the ephemeral TCP source port
  (fixes the original stub so pongs actually return)
- Add `peers` CLI command to dump the discovery table (endpoint/hop/
  state/ping)
- Add discovery tunables to constants.h (fanout, max hops, target
  connections, timeouts, caps)
2026-07-22 23:18:57 +02:00
dcrubro 1345ff7fa6 IPv6 + IPv4 dual-stacking 2026-06-11 10:54:04 +02:00
dcrubro da50b4e8c1 Start IPv6 - Lord help me 2026-06-03 11:20:19 +02:00
dcrubro 00bd711501 remove proof 2026-05-29 14:31:24 +02:00
dcrubro 17ef3b74fd remove from mempool on mine; TEMPORARY log math proof of fee inclusion in coinbase tx 2026-05-29 14:28:27 +02:00
dcrubro c1914dc3e7 add optional fee argument to send command 2026-05-29 14:00:58 +02:00
dcrubro 39293029c5 recompute state bug fixed 2026-05-29 13:51:34 +02:00
dcrubro 763aeb648f add fee-aware mining, coinbase validation, and reorg-safe orphan handling
Mining: blocks now include mempool txs, select spendable txs by fee, and pay coinbase as base reward + fees in main.c.
 - Consensus: block validation now enforces coinbase accounting and rejects invalid coinbase placement, including coinbase on amount2, in block.c and transaction.c.
 - Chain state: rollback now rebuilds currentSupply/currentReward, and block addition preflights spendability before mutating balances in chain.c.
 - Orphans/reorgs: orphan retry is safer, rollback-triggered sync reattaches orphans immediately, and transient orphan failures no longer drop blocks in orphan_pool.c and main.c.
 - Networking/mempool: node lifecycle now initializes the mempool, broadcasts can exclude one peer, and mempool snapshotting supports mining selection in net_node.c and txmempool.c.
 - Ledger simulation: added non-mutating spendable-transaction selection for block assembly in balance_sheet.c.
2026-05-29 13:44:15 +02:00
dcrubro 41a154a9fd fix pushing to txmempool 2026-05-29 12:49:51 +02:00
dcrubro 91d7bfa4e7 start adding tx system - test broadcast 2026-05-29 12:45:22 +02:00
dcrubro 4cfe85f6f2 orphans and wallet files 2026-05-28 13:01:23 +02:00
dcrubro 4f10f013f6 orphans reorg test 2026-05-15 22:38:18 +02:00
dcrubro f94655a0ed segfaults and orphans 2026-05-15 22:32:34 +02:00
dcrubro 58ff36b218 cli fix 2026-05-15 19:54:48 +02:00
dcrubro 8f3559b3f6 segfault fix 2026-05-15 19:46:57 +02:00
dcrubro 971a4d9e49 auto resync on penalties 2026-05-15 19:33:57 +02:00
dcrubro f9c94876d9 reorg bugs 2026-05-15 19:30:58 +02:00
dcrubro 9405801f6b con timeout 2026-05-15 19:28:21 +02:00
dcrubro 0fb2615d4c sync errors 2026-05-15 19:01:51 +02:00
dcrubro 55ca03f4ff orphan test 2026-05-15 18:49:49 +02:00
dcrubro ce27dafaba todo update, forward block broadcasts, optional echo connect 2026-05-15 18:37:50 +02:00
dcrubro 4201b5bcc6 linux errors 2026-05-15 16:21:33 +02:00
dcrubro 46ff16fc3e linux errors 2026-05-15 16:18:06 +02:00
dcrubro 6dd14ce087 linux errors 2026-05-15 16:12:09 +02:00
dcrubro 644695c018 linux errors 2026-05-15 16:07:16 +02:00
dcrubro 5e520d57f6 thread blocking DAG alloc fix 2026-05-15 13:17:24 +02:00
dcrubro 3337ac85ab reorgs, fetch batching (parallel fetch), orphans 2026-05-15 13:01:27 +02:00
dcrubro ad339dc696 sync 2026-05-15 12:23:07 +02:00
dcrubro 361ac73e45 global externs refactor, some tcp methods 2026-05-14 17:36:40 +02:00
dcrubro 1e9fc9b024 fetch depends 2026-05-08 18:12:42 +02:00
dcrubro 8b40fe7c56 fetch depends 2026-05-08 18:10:21 +02:00
dcrubro 189aa357af fetch depends 2026-05-08 18:07:28 +02:00
dcrubro be2a0f3abf throttling cli arg 2026-05-03 16:37:26 +02:00
dcrubro 318fecc029 millisecond timestamps 2026-05-03 13:58:06 +02:00
dcrubro d4ec88426a blockdetail command, fullverify checks difficulty (needs optimizing), move general functions to utils.h 2026-04-30 00:09:40 +02:00
dcrubro 6cbb16d909 hello and ack exchange 2026-04-25 20:30:13 +02:00
dcrubro bd972bfab6 hello and ack exchange 2026-04-25 20:28:38 +02:00
dcrubro 32b9a57366 tx mempool start, hello packet 2026-04-24 17:14:40 +02:00
dcrubro accdeebee8 'balance all' command 2026-04-23 22:10:14 +02:00
dcrubro d962194334 name 2026-04-23 21:39:56 +02:00
dcrubro a89a912898 quality-of-life improvements, lower client slave thread stack to 512KB (maybe still too much), dynamic fullverify - freeing transactions after verification 2026-04-23 21:34:12 +02:00
dcrubro 9c99eec3a8 TCP Node boilerplate; CLI interface 2026-04-23 16:24:26 +02:00
dcrubro d631eb190d Start doing TCP networking 2026-04-15 21:38:30 +02:00
dcrubro 258ca9474f shorten transaction 2026-04-15 18:46:00 +02:00
dcrubro 1c1d8c5341 test spends multiple 2026-04-15 08:58:28 +02:00
dcrubro e55a0b54d0 fix some warnings 2026-04-10 18:36:16 +02:00
dcrubro eb7c29abb1 pragma packing 2026-04-10 16:36:37 +02:00
dcrubro 24f20c81f8 rename 2026-04-03 17:02:46 +02:00
dcrubro 7aafaa4196 note 2026-04-03 16:08:33 +02:00
dcrubro ae64bb9dfc temoporarily changed DAG size for testing, fix TX loading, move some TX logic to Transaction_Init() 2026-04-03 15:20:13 +02:00
dcrubro b83f52a448 balance sheet save/load 2026-04-03 11:43:02 +02:00
dcrubro 6800ce2b60 test send 2026-04-02 21:52:59 +02:00
dcrubro df7787ed2d balance sheet stuff, added khash hashmaps 2026-04-02 21:21:12 +02:00
dcrubro b20ba9802e Full DAG size, epoch scaling etc. 2026-04-01 18:47:59 +02:00
dcrubro 406ec95139 diff 2026-04-01 15:07:16 +02:00
dcrubro dfea98aee2 update storage 2026-04-01 15:01:25 +02:00
dcrubro 06e6f02b86 Figured out the reward scheme 2026-04-01 11:56:09 +02:00
dcrubro 075793c24c huge chain test, added 1.5% yearly inflation at 3.5 million blocks 2026-03-30 23:46:22 +02:00
dcrubro 6f595b86b6 packets 2026-03-30 15:50:22 +02:00
dcrubro b47ff30bc7 difficulty calculation, move from randomx to autolykos2 2026-03-30 15:42:28 +02:00
dcrubro c358115af4 stuff 2026-03-30 09:06:17 +02:00
dcrubro 50e357d8a2 Monero-style emission 2026-03-29 23:30:31 +02:00
dcrubro 0d7adc39e0 BigInts, save/load, will make a calculation for block rewards soon 2026-03-29 22:18:57 +02:00
dcrubro 57bfe61c13 Copied TCP impl from other project, basic Block implementation, randomx pow, signing via secp256k1 2026-03-29 17:18:23 +02:00