# Mics Blockchain cung cấp 3 tính năng chính: Tính phi tập trung (Decentralization) – Độ bảo mật (Security) – Khả năng mở rộng (Scalability) - smart contract: là một chương trình chạy trên blockchain, giúp tự động hóa việc thực hiện các điều khoản khi điều kiện được đáp ứng. Khi đã deploy trên blockchain, smart contract không thể bị sửa đổi. Lấy ví dụ, A chuyển 10 ETH cho B trên mạng Ethereum, B sẽ tự động chuyển 1,000 USDT cho A. nghe có vẻ giống giao dịch trung gian :v - ERC20 là tiêu chuẩn chung để tạo token (token có thể hiểu là tài sản hoặc đại diện cho tài sản điện tử) trên mạng ETH z Cấu trúc của tiêu chuẩn ERC-20 bao gồm 6 hàm bắt buộc: TotalSupply: Hàm thể hiện tổng số token trong thị trường. BalanceOf: Chức năng thể hiện số dư của một ví. Transfer: Hàm chuyển token đến một địa chỉ ví nhất định. TransferFrom: Hàm chuyển token từ một địa chỉ ví nhất định. Approve: Hàm cho phép người ngoài có thể sử dụng số lượng token nhất định của chủ sở hữu. Allowance: Hàm cho phép chủ sở hữu token có thể thay đổi hàm Approve, như số lượng token cho phép… Các hàm không bắt buộc: Name: Tên token và chắc chắn không trùng với những tên token khác. Symbol (Ticker): Ký hiệu token. Khác với Name, Symbol giữa những token có thể giống nhau. Decimals: Số thập phân nhỏ nhất mà token có thể giao dịch. # Deploy testnet Ta sẽ sử dụng [Kurtosis](https://docs.kurtosis.com/install/). Tham khảo [hướng dẫn cài đặt](https://geth.ethereum.org/docs/fundamentals/kurtosis). Mạng cần tạo tối thiểu sẽ có 3 node, trong đó Kurtosis sẽ tạo ra nhiều container khác nhau. Cụ thể có 3 loại chính: - vc: Validator Client, chịu trách nhiệm ký và đề xuất block trong PoS. Validator Client thường kết nối với một Consensus Client (CL). - el: Execution Client, chịu trách nhiệm xử lý giao dịch, thực thi smart contract và lưu trạng thái blockchain - cl: Consensus Client, thực hiện cơ chế đồng thuận Proof of Stake (PoS) để xác thực block. **Mỗi el và cl sẽ tạo thành 1 node hoàn chỉnh** Với file net.yaml, ở đây chúng ta sẽ config sơ sơ cho mạng testnet của mình: ``` participants: - el_type: geth cl_type: lighthouse count: 2 - el_type: geth cl_type: teku network_params: network_id: "63862946" prefunded_accounts: '{"0xd5d0E440Fc0a7334620EB08bd38e4d090805DD57": {"balance": "1000ETH"}, "0xfC8860dda3798a9B794B465b808D97C3499b8e0d": {"balance": "100ETH"}}' additional_services: - dora ``` Vì mặc định testnet sẽ không cung cấp token để giao dịch và sau khi đã deploy thì không thể sửa được nữa nên ta sẽ thêm một dòng thuộc tính `prefunded_accounts` để cung cấp eth cho 2 tài khoản khi mạng được deploy. Các accounts này có thể tạo bằng lệnh geth: `geth --datadir node1/ account new`, sau khi tạo thành công nó sẽ yêu cầu nhập mật khẩu và cung cấp địa chỉ của account cùng với file key. Mình nghĩ nên lưu lại địa chỉ account để lát nữa tiện thao tác ``` sandy@sandy-VM:~/blockchain$ geth --datadir node3/ account new INFO [02-09|22:50:52.634] Maximum peer count ETH=50 total=50 INFO [02-09|22:50:52.636] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory" Your new account is locked with a password. Please give a password. Do not forget this password. Password: Repeat password: Your new key was generated Public address of the key: 0x080249d45C94173aCA2F07188d6dBe30EDBde57d Path of the secret key file: node3/keystore/UTC--2025-02-09T15-50-55.292607915Z--080249d45c94173aca2f07188d6dbe30edbde57d - You can share your public address with anyone. Others need it to interact with you. - You must NEVER share the secret key with anyone! The key controls access to your funds! - You must BACKUP your key file! Without the key, it's impossible to access account funds! - You must REMEMBER your password! Without the password, it's impossible to decrypt the key! ``` Như trên là coi như tạo xong account, chúng ta sẽ tạo 2 cái để giao dịch qua lại. Deploy ethereum testnet với kurtosis chỉ cần 1 dòng: `kurtosis run --enclave testnet github.com/ethpandaops/ethereum-package --args-file net.yaml` Kurtosis sẽ tự khởi chạy engine và enclave, nếu không có lỗi thì ra thế này là xong ``` UUID Name Ports Status 8b5e9c3404ce cl-1-lighthouse-geth http: 4000/tcp -> http://127.0.0.1:32813 RUNNING metrics: 5054/tcp -> http://127.0.0.1:32814 tcp-discovery: 9000/tcp -> 127.0.0.1:32815 udp-discovery: 9000/udp -> 127.0.0.1:32777 85fa8f196df6 cl-2-lighthouse-geth http: 4000/tcp -> http://127.0.0.1:32816 RUNNING metrics: 5054/tcp -> http://127.0.0.1:32817 tcp-discovery: 9000/tcp -> 127.0.0.1:32818 udp-discovery: 9000/udp -> 127.0.0.1:32778 b33178a14fde cl-3-teku-geth http: 4000/tcp -> http://127.0.0.1:32819 RUNNING metrics: 8008/tcp -> http://127.0.0.1:32820 tcp-discovery: 9000/tcp -> 127.0.0.1:32821 udp-discovery: 9000/udp -> 127.0.0.1:32779 bfa8370696e8 dora http: 8080/tcp -> http://127.0.0.1:32824 RUNNING 1f821d0f688d el-1-geth-lighthouse engine-rpc: 8551/tcp -> 127.0.0.1:32800 RUNNING metrics: 9001/tcp -> http://127.0.0.1:32801 rpc: 8545/tcp -> 127.0.0.1:32798 tcp-discovery: 30303/tcp -> 127.0.0.1:32802 udp-discovery: 30303/udp -> 127.0.0.1:32774 ws: 8546/tcp -> 127.0.0.1:32799 5910eef1a9c5 el-2-geth-lighthouse engine-rpc: 8551/tcp -> 127.0.0.1:32805 RUNNING metrics: 9001/tcp -> http://127.0.0.1:32806 rpc: 8545/tcp -> 127.0.0.1:32803 tcp-discovery: 30303/tcp -> 127.0.0.1:32807 udp-discovery: 30303/udp -> 127.0.0.1:32775 ws: 8546/tcp -> 127.0.0.1:32804 773de743923b el-3-geth-teku engine-rpc: 8551/tcp -> 127.0.0.1:32810 RUNNING metrics: 9001/tcp -> http://127.0.0.1:32811 rpc: 8545/tcp -> 127.0.0.1:32808 tcp-discovery: 30303/tcp -> 127.0.0.1:32812 udp-discovery: 30303/udp -> 127.0.0.1:32776 ws: 8546/tcp -> 127.0.0.1:32809 60400129105c validator-key-generation-cl-validator-keystore <none> RUNNING 81db79c737e1 vc-1-geth-lighthouse metrics: 8080/tcp -> http://127.0.0.1:32822 RUNNING 66e1b15b4427 vc-2-geth-lighthouse metrics: 8080/tcp -> http://127.0.0.1:32823 RUNNING ``` lúc này ta có thể truy cập vào url của dora để theo dõi mạng `bfa8370696e8 dora http: 8080/tcp -> http://127.0.0.1:32824` Gõ `docker ps` để tìm container id của 2 node `el-1-geth-lighthouse` và `el-2-geth-lighthouse` vì 2 thằng này sẽ chịu trách nhiệm giao dịch Thực hiện kết nối tới 2 node này thông qua rpc: `docker exec -it 75996ab99438 geth attach http://localhost:8545` ``` root@sandy-VM:~# docker exec -it 75996ab99438 geth attach http://localhost:8545 Welcome to the Geth JavaScript console! instance: Geth/v1.15.0-unstable-0ad0966c-20250204/linux-amd64/go1.23.5 at block: 776 (Sun Feb 09 2025 15:23:44 GMT+0000 (UTC)) datadir: /data/geth/execution-data modules: admin:1.0 debug:1.0 eth:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0 To exit, press ctrl-d or type exit > eth.accounts [] ``` Lý do chạy lệnh accounts không trả về kết quả là do chưa có tài khoản nào trong datadir hay chưa có file key. Ta cần một tài khoản để có thể chuyển và nhận tiền. 2 accounts lúc nãy tạo sẽ có một file dạng `UTC...` trong folder keystore của datadir, hãy copy nó vào trong từng container. ``` root@sandy-VM:~# docker exec -it 75996ab99438 sh / # cd /data/geth/execution-data /data/geth/execution-data # cd keystore/ /data/geth/execution-data/keystore # vi UTC--2025-02-05T11-01-27.277458763Z--d5d0e440fc0a7334620eb08bd38e4d090805dd57 /data/geth/execution-data/keystore # cat UTC--2025-02-05T11-01-27.277458763Z--d5d0e440fc0a7334620eb08bd38e4d090805dd57 {"address":"d5d0e440fc0a7334620eb08bd38e4d090805dd57","crypto":{"cipher":"aes-128-ctr","ciphertext":"7500110df72d4be8a2ae05a4d81ac99a8ca0849f9fcf25ddc8cb4e04ef20b657","cipherparams":{"iv":"25dad22c37f1e3b00324b78fbc1a8fd7"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"7edcff5130c81fa2cffce104c3696a6533e9e6f967a8df2fd151ab79431d5452"},"mac":"4d8fac489f74ae11c49ff307254effc3115a82378a5cdd38100b98fff3cd176a"},"id":"fd6762a7-7f86-4b16-875d-d81d4c1d167f","version":3} /data/geth/execution-data/keystore # exit root@sandy-VM:~# docker exec -it 75996ab99438 geth attach http://localhost:8545 Welcome to the Geth JavaScript console! instance: Geth/v1.15.0-unstable-0ad0966c-20250204/linux-amd64/go1.23.5 at block: 802 (Sun Feb 09 2025 15:28:56 GMT+0000 (UTC)) datadir: /data/geth/execution-data modules: admin:1.0 debug:1.0 eth:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0 To exit, press ctrl-d or type exit > eth.accounts ["0xd5d0e440fc0a7334620eb08bd38e4d090805dd57"] > eth.getBalance("0xd5d0e440fc0a7334620eb08bd38e4d090805dd57") 1e+21 ``` Giờ thì có eth để giao dịch rồi, làm tương tự cho container còn lại >[!Warning] Chưa thể unlock account, send transactions >Việc unlock account bằng geth có thể sẽ gặp nhiều khó khăn >Chúng ta sẽ thay thế bằng cách sử dụng ví metamask để giao dịch thay vì sử dụng geth 1. Truy cập vào https://metamask.io/ và cài đặt extension metamask về ![image](https://hackmd.io/_uploads/HJQw1U_Y1l.png) cài xong mở extension lên ![image](https://hackmd.io/_uploads/SkufU8dYyx.png) 2. Tạo ví ![image](https://hackmd.io/_uploads/H10vUUdFkg.png) ![image](https://hackmd.io/_uploads/H1K58IuYJl.png) Đoạn sau chỉ cần đặt tên ví và create account là xong ![image](https://hackmd.io/_uploads/S11ALIOK1l.png) Nên lưu lại địa chỉ của ví vì lát nữa ta sẽ cần địa chỉ của ví để tạo ETH khi deploy lại mạng 3. Deploy lại mạng Sửa lại địa chỉ 2 account trong file net.yaml về địa chỉ của ví metamask vừa tạo và deploy lại mạng (tham khảo lại từ đầu). Lúc này ta không cần copy key vào container của el node nữa ![image](https://hackmd.io/_uploads/ryiGF8_K1g.png) 5. Kết nối vào mạng ![image](https://hackmd.io/_uploads/HkfBKIdtke.png) Trong đống này chọn options `add a custom network` ![image](https://hackmd.io/_uploads/SkNoY8uFJe.png) - RPC URL lấy trong đống khi chạy kurtosis thành công hoặc xem lại container, nó sẽ có dạng kiểu `0.0.0.0:32904->8545/tcp`(trong docker) hoặc `rpc: 8545/tcp -> 127.0.0.1:32904`(log kurtosis) lấy cái có port 5 số. - Chain ID chúng ta đã định nghĩa từ trước trong file `net.yaml`, nếu không nhớ thì xem lại - Currency symbol chọn ETH Và cuối cùng nhớ kết nối với mạng của mình, đừng nhầm với mainnet, nếu không là không có tiền đâu :( ![image](https://hackmd.io/_uploads/HkWKo8uFJe.png) Một chút cảm giác của người giàu: ![image](https://hackmd.io/_uploads/B1uho8_YJx.png) ## Giao dịch ![image](https://hackmd.io/_uploads/By-j38dY1x.png) Chọn địa chỉ nhận và số lượng ETH gửi ![image](https://hackmd.io/_uploads/rystTLuFyx.png) Mình sẽ gửi 1 ETH tự ví `account 1` đến ví `testnet_account_2` ![image](https://hackmd.io/_uploads/S1MAT8OYyg.png) Đoạn này nó bắt mình confirm với gasfee thì ok thôi ![image](https://hackmd.io/_uploads/SkhGCLdK1x.png) Giao dịch thành công Để ý sẽ thấy khi ta giao dịch từ ví 1 sang ví 2 thì nó sẽ trong trạng thái pending chứ không hoàn tất ngay lập tức, bởi vì còn nhiều công đoạn phía sau nữa. - Khi giao dịch diễn ra, lớp el (ở đây ta dùng geth) sẽ nhận thông tin và kiểm tra tính hợp lệ của giao dịch có thể bao gồm các thông tin: Sender có đủ ETH không? Nonce có hợp lệ không? Chữ ký hợp lệ không? >[!Note] Số nonce >Tránh replay attack: Nếu không có nonce, một giao dịch có thể bị phát lại nhiều lần. >Xác định thứ tự giao dịch: Ethereum không thể xử lý giao dịch mới nếu giao dịch trước đó (nonce thấp hơn) chưa được xác nhận >[!Note] Chữ ký >Ethereum sử dụng Elliptic Curve Digital Signature Algorithm (ECDSA) để tạo chữ ký giao dịch. Chữ ký này gồm 3 thành phần chính: >`r`: Một phần của chữ ký, được sinh ra từ private key. >`s`: Một phần của chữ ký, giúp xác minh tính hợp lệ. >`v`: Dùng để xác định chuỗi (chain) của giao dịch. >**Chữ ký dùng để:** >Người gửi thực sự là chủ của địa chỉ. >Không ai có thể chỉnh sửa giao dịch sau khi đã ký. >Không thể giả mạo chữ ký nếu không có private key. Nếu hợp lệ, Geth sẽ: - Lưu giao dịch vào `mempool` (bộ nhớ đệm chờ xử lý) - Gửi giao dịch đến **Consensus Layer** (Lighthouse & Teku) Giao dịch chưa được chấp nhận ngay lập tức, nó cần được đưa vào block bởi một validator - Mỗi slot (vài chục giây), một validator ngẫu nhiên trong mạng được chọn để tạo block mới - Validator mới sẽ lấy các giao dịch từ mempool - Tạo một block mới chứa giao dịch - Gửi block này đến toàn bộ mạng để xác thực - Các validator khác sẽ kiểm tra block này - Nếu đồng ý block hợp lệ, các validator sẽ bỏ phiếu (attestation) để xác nhận block Điều kiện để block được chấp nhận là 51% số validator phải đồng ý. Khi đạt 51% số phiếu, block được finalized (lúc này thì thông tin sẽ không thể bị chỉnh sửa) >[!Note] Gas fee >gas càng cao thì giao dịch sẽ được xếp ở vị trí ưu tiên trong mempool để tối ưu hóa lợi nhuận >nếu muốn đẩy nhanh giao dịch thì chỉ cần tăng gas fee lên ## Deploy smart contract 1. Sử dụng Remix IDE # Smart contract sercurity # On-chain analysis Onchain là dữ liệu phi tập trung ai cũng có thể truy cập vào. Chúng là những dữ liệu bao gồm: các địa chỉ ví, các giao dịch, thời gian giao dịch, số lượng tiền điện tử được chuyển đi hoặc nhận về,.. được lưu trữ trực tiếp trên blockchain. Căn cứ vào dữ liệu này, nhà đầu tư sẽ dễ dàng phân tích các xu hướng thị trường, dự đoán giá cả và xác định các hành vi của các nhà giao dịch