Beginnersgids voor TON: Accounts, tokens en beveiliging
Achtergrond
TON (The Open Network) is een gedecentraliseerd blockchainplatform dat in eerste instantie is ontworpen en ontwikkeld door het Telegram-team. TON heeft als doel een goed presterend en schaalbaar blockchain platform te bieden om grootschalige gedecentraliseerde applicaties (DApps) en smart contracts te ondersteunen.
TON is uniek omdat het makkelijk te gebruiken is, diep geïntegreerd met Telegram, waardoor gewone mensen gemakkelijk tokens kunnen gebruiken. Tegelijkertijd is het complex, met een architectuur die verschilt van andere blockchains, en het maakt gebruik van een niet-mainstream smart contract taal genaamd FunC.
Vandaag bespreken we de kenmerken van TON en de veiligheid van gebruikersactiva vanuit het perspectief van accounts, tokens en transacties.
Kenmerken van TON
Account aanmaken
De methode voor het genereren van een accountadres op TON is anders dan op de meeste blockchains; het is een smart contract adres. Ten eerste begint alles met een privésleutel. TON gebruikt voornamelijk het Ed25519 algoritme om een publieke sleutel te genereren, waarbij het proces als volgt verloopt:
Er zijn twee vormen van de openbare sleutel: één is de onbewerkte openbare sleutel berekend uit de privésleutel, die er als volgt uitziet:
E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D
De andere is een “verfraaide” publieke sleutel, die wat informatie en controlebits bevat en er als volgt uitziet:
Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2
Als je denkt dat alleen het verkrijgen van de publieke sleutel je in staat stelt om het accountadres te verkrijgen zoals in Ethereum, dan heb je het mis. Alleen de publieke sleutel van de gebruiker hebben is niet genoeg om het accountadres van de gebruiker te berekenen.
Zoals gezegd is het accountadres van de gebruiker een smart contractadres, maar hoe kun je een smart contract inzetten zonder een account te hebben?
De juiste volgorde is om eerst het adres te berekenen, een beginbedrag aan tokens te ontvangen en dan het contract in te zetten. Het proces van het berekenen van het rekeningadres wordt weergegeven in het volgende diagram:
Het adres van een gebruiker komt ook in meerdere vormen. Ten eerste is er de ruwe vorm, die er als volgt uitziet:
0:b4c1b2ede12aa76f4a44353944258bcc8f99e9c7c474711a152c78b43218e296
Dan is er een gebruiksvriendelijk formulier, dat er als volgt uitziet:
Hoofdnet:
- Stuiterbaar:
EQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0MhjilkPX
- Niet-stuiterbaar:
UQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0Mhjilh4S
Testnet:
- Stuiterbaar:
kQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0Mhjilvhd
- Niet-stuiterbaar:
0QC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0MhjilqWY
Als je goed naar deze adressen kijkt, zie je dat ze alleen verschillen in de eerste en laatste paar tekens, terwijl de middelste account_id
hetzelfde zijn.
We kunnen echter nog steeds de relatie tussen de openbare sleutel en het accountadres niet zien.
Het geheim zit in de initial data
aan het begin, die de publieke sleutel van een gebruiker bevat, waardoor de gebruiker het wallet contract kan controleren. De workchainId
is eenvoudig te begrijpen; TON is niet één keten, maar bestaat uit vele scherven.
Elke shard is een deel van het hele netwerk en behandelt specifieke accounts en transacties. Om slimme contracten te lokaliseren en te beheren, is het nodig om aan te geven in welke shard ze zich bevinden. Wat is het verschil tussen Bounceable
en Non-bounceable
?
Dit heeft te maken met de manier waarop slimme contracten werken, maar laten we verder kijken.
Portemonnee contract
Hieronder staat een fragment van de broncode van een gebruikersportemonneecontract. Het laat zien dat wanneer het een bericht ontvangt van de gebruiker, het vier parameters leest: stored_seqno
, stored_subwallet
, public_key
en plugins
:
wallet-v4-code.fc
() recv_external(slice in_msg) impure {
var signature = in_msg~load_bits(512);
var cs = in_msg;
var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
throw_if(36, valid_until <= now());
var ds = get_data().begin_parse();
var (stored_seqno, stored_subwallet, public_key, plugins) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256), ds~load_dict()); ;;##The Initial Data
ds.end_parse();
throw_unless(33, msg_seqno == stored_seqno);
throw_unless(34, subwallet_id == stored_subwallet);
throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));
//...
}
Wanneer dit contract voor de gebruikersportemonnee wordt ingezet, vereist het enkele initiële parameters, waaronder een 256-bits public_key
. Dit zorgt ervoor dat elke gebruiker een uniek contractadres heeft, zelfs wanneer dezelfde contractcode wordt gebruikt. Dit zorgt ervoor dat elke gebruiker een uniek contractadres heeft, zelfs als hij dezelfde contractcode gebruikt.
Elke transactie die door de gebruiker wordt geïnitieerd, moet worden ondertekend met in_msg
en vervolgens geverifieerd door het wallet contract (check_signature), waarna het contract bewerkingen uitvoert op de blockchain. Hieruit kunnen we afleiden dat de publieke sleutel van een gebruiker kan corresponderen met meerdere portemonnee-adressen.
Het implementeren van verschillende portemonneecontracten of het gebruik van verschillende initialisatiegegevens zal resulteren in totaal verschillende contractadressen.
Jetton Penning
Een token vertegenwoordigt een actief op de blockchain, waardoor het een fundamenteel element is dat we moeten begrijpen. Jetton is de standaardvorm van TON-tokens en bestaat uit twee contracten: Jetton-minter en Jetton-wallet.
Wanneer een token wordt uitgegeven, wordt een Jetton-minter contract aangemaakt. Deze contractinitialisatie registreert informatie zoals de totale voorraad tokens, de beheerder, portemonneecode en andere details.
Wanneer tokens worden uitgedeeld aan gebruikers, zet het Minter-contract voor elke gebruiker een portemonneecontract in. Tijdens de initialisatie van het contract wordt het saldo van de gebruiker, het eigendom, het Minter-contractadres van de token, de portemonneecode van de gebruiker en andere relevante informatie vastgelegd. Elke gebruiker heeft een individueel ingezet contract.
Het is belangrijk om op te merken dat het contract dat hier wordt aangemaakt een portemonneecontract is voor het beheren van specifieke Jetton-tokens, wat verschilt van het account-portemonneecontract van de gebruiker. De owner_address
die hier wordt geregistreerd is het adres van de accountportemonnee van de gebruiker.
Als gebruiker Alice tokens overdraagt aan gebruiker Bob, is de aanroeprelatie als volgt:
Alice ondertekent de transactie via een off-chain app en stuurt een operationeel commando via haar wallet contract. Deze commando’s zullen verder haar token wallet aanroepen om de overdracht uit te voeren. Wanneer Bob’s token wallet de tokens ontvangt, stelt het Bob’s wallet contract op de hoogte (het eigenaarsadres van Bob’s Jetton-wallet).
Als er tijdens de transactie gas overblijft, wordt dit teruggestuurd naar het juiste adres, meestal het rekeningcontract van Alice.
Hieronder staat een voorbeeld van een Jetton token overdracht die door de Tonviewer browser is verwerkt:
Terwijl een ERC20 overdracht slechts een enkele contractaanroep vereist, vereist een Jetton token overdracht minstens vier contractaanroepen. Deze methode is ontworpen om on-chain concurrency mogelijk te maken, waardoor de transactie-efficiëntie verbetert.
Transacties
Wanneer een bepaalde gebeurtenis plaatsvindt in een TON account, wordt er een transactie gestart. De meest voorkomende gebeurtenis is “een bericht ontvangen”. Een transactie bevat de volgende elementen:
- Het inkomende bericht dat het contract initieel triggert (met speciale triggermethoden beschikbaar).
- Contractacties als gevolg van het inkomende bericht, zoals het bijwerken van de opslag van het contract (optioneel).
- Uitgaande berichten naar andere deelnemers (optioneel).
Er zijn verschillende belangrijke kenmerken waar je op moet letten bij transacties:
- Asynchroon: TON transacties worden niet in één enkele aanroep voltooid; ze kunnen het doorgeven van berichten aan meerdere verschillende slimme contracten vereisen om een reeks aanroepen uit te voeren. Door de verschillende routing in de sharded ketens, kan TON de volgorde van berichtaflevering tussen meerdere slimme contracten niet garanderen.
- Kosten: De asynchrone aard van transacties maakt het moeilijk om de verbruikte vergoedingen in te schatten. Daarom sturen portemonnees vaak een beetje extra token als vergoeding bij het initiëren van een transactie. Als het opgeroepen contract een goed mechanisme heeft voor het afhandelen van vergoedingen, worden de resterende vergoedingen teruggestuurd naar de portemonnee van de gebruiker. Gebruikers kunnen merken dat hun portemonneetokens plotseling afnemen en na een paar minuten weer toenemen, wat te wijten is aan dit mechanisme.
- Stuiteren: Bounce is een foutafhandelingsmechanisme in contracten. Als het aangeroepen contract niet bestaat of een fout geeft, en de transactie is ingesteld als bouncebaar, dan wordt een bounce bericht teruggestuurd naar het aanroepende contract. Als een gebruiker bijvoorbeeld een overschrijving initieert en er treedt een fout op tijdens het proces, dan is een bounce bericht nodig zodat het wallet contract van de gebruiker zijn saldo kan herstellen. Bijna alle interne berichten die verstuurd worden tussen slimme contracten zouden bouncebaar moeten zijn, wat betekent dat hun “bounce” bit ingesteld zou moeten zijn.
Veiligheid van activa
TON heeft veel functies die tot beveiligingsproblemen kunnen leiden, dus gebruikers moeten zich bewust zijn van een aantal veelvoorkomende valkuilen.
Aanval op inhouding van vergoedingen
Zoals gezegd, wallets moeten vaak een beetje extra kosten sturen om te voorkomen dat een transactie mislukt, wat een kans biedt voor aanvallers. Als je een TON wallet gebruiker bent, ben je misschien een situatie tegengekomen waarin je wallet vaak verschillende NFT’s of tokens ontvangt.
In eerste instantie lijken dit vuilnis token airdrops, maar bij het controleren van de transactie details, ontdek je dat ze kunnen worden verkocht voor een aanzienlijk bedrag. Wanneer je echter een transactie probeert te starten, merk je dat de vereiste vergoeding extreem hoog is (1 ton). Op dit punt moet je voorzichtig zijn, want dit kan oplichterij zijn.
Aanvallers creëren een zorgvuldig samengesteld tokencontract dat ervoor zorgt dat de portemonnee een buitensporig hoge overdrachtsvergoeding inschat, maar in werkelijkheid wordt alleen de vergoeding ingehouden en wordt er geen overdrachtsbericht verzonden.
Phishing met eerste en laatste cijfer
First and last digit phishing is niet uniek voor TON; deze phishing-aanval bestaat op veel grote blockchains. Aanvallers genereren een valse account voor elk gebruikersadres op het netwerk met dezelfde eerste en laatste cijfers.
Wanneer een gebruiker een overdracht start, stuurt de aanvaller ook een kleine overdracht, na de transactie van de gebruiker, om een record achter te laten in de transactiegeschiedenis van de gebruiker. Wanneer de ontvangende gebruiker tokens terug wil sturen, kan hij het adres uit zijn transactiegeschiedenis kopiëren, wat het adres van de aanvaller kan zijn, wat leidt tot een overdracht naar het verkeerde adres. De aanvaller heeft nauwkeurig het gedrag van de gebruiker uitgebuit.
Commentaar Phishing
Bij het overmaken van tokens op TON kunnen gebruikers een opmerking toevoegen om de transactie te annoteren. Deze functie wordt vaak gebruikt bij stortingen op exchanges, waar exchanges meestal vereisen dat gebruikers hun gebruikers-ID in het commentaar bij de storting vermelden. Deze functie wordt echter vaak misbruikt door kwaadwillende actoren, die frauduleuze informatie in de opmerkingen schrijven om de activa van gebruikers te stelen. Bijvoorbeeld:
Gebruikers moeten vooral voorzichtig zijn met de “Anonymous Telegram Number” NFT. Als een gebruiker zijn Telegram account activeert met een Anonymous Telegram Number, maar Two-Step Verification niet inschakelt, en deze NFT wordt gephisht, kan de hacker direct inloggen op het Telegram account en doorgaan met de daaropvolgende diefstal van activa en frauduleuze activiteiten.
Smart Contract kwetsbaarheden
Kwetsbaarheden in de beveiliging van slimme contracten kunnen leiden tot het verlies van fondsen die zijn opgeslagen in het contract. Gebruikers moeten projecten kiezen die grondig zijn gecontroleerd. De slimme contracten van TON zijn voornamelijk geprogrammeerd met de FunC taal, hoewel sommige het meer geavanceerde Tact of het lagere niveau Fift gebruiken.
Al deze talen zijn zeer origineel. Nieuwe programmeertalen brengen nieuwe beveiligingsrisico’s met zich mee, in het bijzonder voor ontwikkelaars, die veilige codeergewoonten moeten aanleren, de beste beveiligingspraktijken onder de knie moeten krijgen en strenge beveiligingsaudits moeten ondergaan voordat ze worden ingezet in de productieomgeving. Vanwege de beperkte ruimte zal dit artikel niet in detail ingaan op contractbeveiliging.
Valse storting
Gebruikers van een portemonnee of beurs moeten zich bewust zijn van nepstortingsaanvallen, die meestal in twee vormen voorkomen:
- Valse tokens: Een aanvaller geeft een token uit met metadata die identiek zijn aan het doeltoken. Als het geautomatiseerde stortingsprogramma niet controleert of het token van het juiste mintercontract is, kan dit leiden tot onjuiste stortingen.
- Stuiteren: Het overdrachtsproces van TON vereist een aanroepingsrelatie tussen de portefeuillecontracten van twee gebruikers. Als het portefeuillecontract van de ontvanger niet bestaat en de transactie is ingesteld als bounceable, zal het bericht terugstuiteren en het oorspronkelijke geld, minus de vergoeding, zal worden teruggestuurd naar de verzender. Geïnteresseerden in de details kunnen ons vorige artikel over valse stortingen raadplegen.
Conclusie
Dit artikel introduceerde enkele fundamentele technische principes van TON vanuit het perspectief van het aanmaken van sleutels en portemonnees, tokenvormen en transactiekenmerken. Het onderzocht ook potentiële veiligheidsproblemen bij het gebruik van TON, in de hoop je leerproces te inspireren.