---
# System prepended metadata

title: blockchain

---

# 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