Nobody else waits
A payment from A to B changes only A’s chain and B’s chain. Every other wallet’s chain stays as it is, so payments between other people never queue behind yours.
Instead of one shared blockchain, every OneEur wallet has its own chain. A payment adds one block to the sender’s chain and one to the receiver’s. That is why it never waits in line.
A signs a send block on their own chain. Their balance goes down and the money is now pending for B.
The primary chain holder checks the signature and balance and adds the block. It handles one block at a time, so if the same money is spent twice, only the first spend goes through.
B signs an open or receive block on their chain that points to A’s send. B’s balance goes up. No other chain changes.
A payment from A to B changes only A’s chain and B’s chain. Every other wallet’s chain stays as it is, so payments between other people never queue behind yours.
Until B adds the receive block, the money is pending for B. The OneEur app collects pending payments automatically, so for the person being paid it simply arrives.
One chain holder, the primary, checks each new block and adds it. It handles one block at a time, so if two blocks try to spend the same money, the first one is added and the second is refused as a fork. The app gets its answer as soon as the primary has added the block, usually within a few milliseconds.
Right after that, the block is copied to all other chain holders in the background, in order and in batches. Each holder has its own sender, so a slow or unreachable holder never slows payments down.
A holder that was offline compares its block hashes with the primary’s and fetches what it is missing in batches of 1,000. A copy that arrives before the block it builds on is kept aside until that block arrives.
New payments are refused with primary_unavailable until it is back, so no money can be spent twice in the meantime. Balances and history can still be read from the other holders.
The first block of the genesis wallet creates the whole supply. No rule can create more coins after that. Every holder checks this at all times:
sum of balances + sum of pending sends == total supplyAmounts are whole numbers of units (1 OEUR = 100,000,000 units), so there is no rounding anywhere.
:crypto (OpenSSL), no custom cryptooe_ed25519_… with a built-in checksumONEEUR-BLOCK-V1{
"type": "send",
"algorithm": "ed25519",
"account": "oe_ed25519_…",
"height": 2,
"previous": "<64 hex>",
"balance": "2099999000000000",
"link": "oe_ed25519_…",
"memo": "March rent",
"hash": "<64 hex>",
"signature": "<128 hex>"
}
Each block points to the one before it on the same chain. Amounts are sent as strings so that no app loses precision.
See every block live in the explorer"ONEEUR-BLOCK-V1" 15 bytes format name
type 1 byte 1 = open, 2 = send, 3 = receive
account key algorithm (1) + length (2) + public key
height 8 bytes position in the wallet’s chain
previous 32 bytes hash of the previous block
balance 16 bytes balance after this block
link key / 32 send: receiver · open/receive: the send’s hash
memo length 1 byte 0–128
memo 0–128 UTF-8 text
hash = SHA-256(bytes above)
signature = Ed25519(wallet key, hash)
bad_signaturebad_balanceforkbad_previous, gapunknown_sendalready_existsmemo_mismatchself_sendunsupported_algorithmEach holder stores every wallet’s chain in its own append-only file, in height order. When a send to a wallet is accepted, an incoming note is added to the receiver’s file too, so each file shows on its own what is still pending.
A block can change two files (the sender’s and the receiver’s), so it is first written to the holder’s journal and flushed to disk. From that moment the block counts. If the machine crashes halfway, the journal is replayed on start and the two files never disagree.
When a holder restarts, it replays every file through the full ledger rules, checking every signature again. It can confirm payments right away while that runs in the background.