📜 [專欄新文章] Tornado Cash 實例解析
✍️ Johnson
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
Tornado Cash 是一個使用 zk-SNARKs 建立的 Dapp,它實現了匿名的代幣交易,這篇文章就用一些程式碼片段,來分享它是怎麼運作的。
本文為 Tornado Cash 研究系列的 Part 3,本系列以 tornado-core 為教材,學習開發 ZKP 的應用,另兩篇為:
Part 1:Merkle Tree in JavaScript
Part 2:ZKP 與智能合約的開發入門
Special thanks to C.C. Liang for review and enlightenment.
我們知道在以太坊上的交易紀錄都是公開的,你可以在 etherscan 上看到某個地址的所有歷史交易紀錄,當然地址是合約的話也是一樣。
也許創建一個新的錢包和地址就好了?假設一個情境是 Alice 想要匿名傳送 1 ETH 給 Bob,Alice 原本的錢包是 A,但她不想讓 A 地址傳給 Bob 的交易紀錄被看到,所以 Alice 創建另一個錢包 B,顯然 B 錢包是空的,Alice 必須把 A 錢包的 1 ETH 傳到 B 錢包,再用 B 錢包的地址傳給 Bob。
但問題就在於,只要追蹤 B 錢包的地址,就能看到 B 的歷史交易紀錄中 A 錢包曾經打幣給 B 錢包,於是到頭來交易還是被追蹤到了。
Tornado Cash 的解決方案,簡單來說,它是一份合約,當你要匿名傳送代幣時,就把一定數量的幣丟進合約裡 (Deposit),此時你會拿到一個 note,長得像這樣:
tornado-eth-0.1-5-0x3863c2e16abc85d72b64d78c68fca5936db2501832e26345226efdfb2bc45804977f167d86b711bb6b4095ddaa646ec93f0a93ac4884a66c1d881f4fc985
note 就是一串字串,擁有這字串的人,就能提領 (Withdraw) 剛剛傳入合約的代幣。握有 note 就代表擁有提款的權利,所以 note 一旦被別人知道,別人就可以把錢給提走。
其中,後面那段亂碼,本篇文章就以「秘密」來稱呼,這個秘密是由 secret 與 nullifier 組成,而這兩個都是在鏈下隨機產生的亂數。
因此 Tornado 的合約基本上會有兩個函式:
Deposit
Withdraw
有興趣的人可以先到 Dapp 上先玩一次看看,使用 Goerli 測試網,這裡可以領 Goerli 的代幣:https://goerli-faucet.slock.it/
Deposit
我們就從 Deposit 開始說起,簡單來說, Deposit 是將資料儲存到合約的 Merkle Tree 上。
剛剛提到的秘密,它是在鏈下產生,由 secret 跟 nullifier 組成,合在一起之後也稱作 preimage,因為我們要對這個 preimage 進行 hash,就會成為 commitment。
合約中 Deposit 如下:
deposit 除了傳送代幣到合約之外,需填入一個參數 _commitment。
我們對 preimage 使用 Pedersen 作為 hash function 加密後產生 commitment,以偽代碼表示如下:
const preimage = secret + nullifier;const commitment = pedersenHash(preimage);
這個 commitment 會成為 Merkle Tree 的葉子,所以合約中的 _insert(commitment) 來自 MerkleTreeWithHistory.sol 的合約,將我們的資料插入 Merkle Tree,然後回傳一個 index 給你,告訴你這個 commitment 在 Merkle Tree 上的位置,最後一起發布成公開的 Deposit 事件。
我們知道 MerkleTree 是將一大筆資料兩兩做雜湊後產生一個唯一值 root,這個 root 就是合約上所儲存的歷史資料。
root 的特性就是只要底下的資料一有更動,就會重新產生新的 root。
所以只要一有用戶 deposit ,就會插入新的葉子到 Merkle Tree 上,於是就會產生新的 root,所以在合約中有一個陣列是用來儲存所有的 root 的 roots:
bytes32[ROOT_HISTORY_SIZE] public roots;
roots 是用來紀錄每個 deposit 的歷史,每一次 deposit 都會創造新的 root,而所有 root 都會被儲存進 roots 裡,於是當你要提領的時候,就要證明你的 commitment 所算出的 root 曾經出現在 roots 裡,代表曾經有 deposit 的動作,因此才可以進行提領。
Withdraw
在 Deposit 之前 Tornado Cash 就會在鏈下產生秘密後交給使用者,擁有這個秘密的人等於擁有提款的權利。
提領的時候,秘密會在鏈下計算後產生 proof,proof 是 withdraw 需要的參數,所以只要確保這個 proof 能夠被驗證,那麼代幣的接收地址 (recipient) 就可以隨便我們填,只要不填上當初拿來 deposit 用的地址,基本上就做到匿名交易的效果了。
也就是說,產生這個 proof 並提交給合約,能夠證明此人知道秘密,但卻不告訴合約秘密本身是什麼。
function withdraw(bytes calldata _proof, bytes32 _root, bytes32 _nullifierHash, address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) external payable nonReentrant;
我們可以清楚看到 withdraw 函式裡沒有接收有關秘密的任何資訊作為參數,也就是秘密不會與合約有所接觸,也不會暴露在 etherscan 上。
回顧 ZKP 所帶來的效果:
鏈下計算
隱藏秘密
在 Tornado Cash 的例子中,我們用秘密來產生證明,完成的鏈下計算包括:
將秘密 hash 成 commitment
算出 Merkle Tree 的 root。
以下是簡化後的 withdraw.circom:
template Withdraw(levels) { signal input root; signal input nullifierHash;
signal private input nullifier; signal private input secret; signal private input pathElements[levels]; signal private input pathIndices[levels];
component hasher = CommitmentHasher(); // Pedersen hasher.nullifier <== nullifier; hasher.secret <== secret; hasher.nullifierHash === nullifierHash;
component tree = MerkleTreeChecker(levels); // MiMC tree.leaf <== hasher.commitment; tree.root <== root; for (var i = 0; i < levels; i++) { tree.pathElements[i] <== pathElements[i]; tree.pathIndices[i] <== pathIndices[i]; }}
component main = Withdraw(20);
從上述代碼就可以看出這份 circuit 的 private 變數有:
secret
nullifier
pathElements
pathIndices
而 public 變數有:
root
nullifierHash
如同我們一開始說過的,秘密就是指 secret 與 nullifier。這裡進行的鏈下計算就是對 secret 與 nullifier 雜湊成 commitment。而使用的 hash function 叫做 Pedersen。
在進行 Merkle Tree 的計算之前,我們還檢查了 nullifier 雜湊後的 nullifierHash 跟 public 變數 nullifierHash 是不是一樣的。
hasher.nullifierHash === nullifierHash;
接下來,開始計算 Merkle Proof,用意是確認經過雜湊後的 commitment 有沒有出現在 Merkle Tree 上,所以我們的 private input 還有 pathElements 與 pathIndices(詳情參考 Part 1 Merkle Tree in JavaScript),讓它跑一趟 Merkle Proof 的計算,最後就能夠算出一個 root,再確認計算後的 root 與我們的 public 變數 root 是否一樣。
tree.root <== root;
於是我們就能產生一個 ZKP 的證明 — 證明 private 變數:secret, nullifier, pathElements, pathIndices 可以計算出 public 變數:root 與 nullifierHash。
把這個證明提交給合約,合約透過 Verifier 驗證 proof 是否正確,以及必須事先確認:
public 變數 root 有在合約的 roots 裡面。
public 變數 nullifierHash 在合約中是第一次出現。
以下附上完整的 withdraw 原始碼:
必須注意 ZKP 是向合約證明使用者填入的 secret 和 nullifier 可以計算出某個 root,但無法保證這個 root 曾經在合約的 roots 歷史上。
所以合約的 withdraw 中,除了 verifyProof 之外,還要事先檢查 ZKP 算出來的 root 是不是真的在歷史上發生過,所以需要 isKnownRoot 的檢查:
function isKnownRoot(bytes32 _root) public view returns(bool)
必須先檢查 isKnownRoot 後才能進行 verifyProof。
經過 verifyProof 驗證成功後,合約就開始進行提款的動作,也就會將代幣傳到 recipient 的地址,最後拋出 Withdrawal 的事件。
nullifier 與 nullifierHash
為什麼我們的秘密不是只有 secret 還要額外加一個 nullifier?
簡單來說,這是為了防止已經提領過的 note 又再提領一次,也就是所謂的 double spend。
require(!nullifierHashes[_nullifierHash], "The note has been already spent");
可以看到 withdraw 需要填入參數 nullifierHash,跟 isKnownRoot 一樣的狀況,我們需要對電路的 public 變數先經過一層檢查之後,才能帶入到 verifyProof 裡面。
nullifierHash 可以理解為這個 note 的 id,但它不會連結到 deposit,因此可以用來紀錄這個 note 是否已經被提領過。
所以當 verifyProof 驗證成功之後,我們要紀錄 nullifierHash 已完成提領:
nullifierHashes[_nullifierHash] = true;
有關為什麼需要事先檢查 public 變數後,才能帶入 verifyProof ,可以參考 Part 2:ZKP 與智能合約的開發入門 提到的 publicSignals 的部分。
附上 Tornado Cash 的架構圖:
簡化版的 tornado-core
tornado-core 的程式碼很簡潔漂亮,所以我模仿該專案自己實作一遍:
simple-tornado:https://github.com/chnejohnson/simple-tornado
這份專案只完成了 tornado-core 的核心部分,不一樣的是我的開發環境使用 hardhat 與 ethers 寫成,而 circom 與 snarkjs 使用官方當前的版本,合約用 0.7.0,測試使用 Typescript 。
比起兩年前的 tornado-core ,simple-tornado 使用的技術更新,可能更適合初學者理解這份專案,但是它有 bug…我在 issues 的地方有紀錄說明。
在開發的過程中,我的順序是先從最小單位的 MiMC hash function 開始玩,發現必須 javascript 算一次 hash、solidity 算一次、circom 再算一次,確保這三個語言對同一個值算出同樣的 hash 之後,才能放心去做更複雜的 Merkle Tree。
總結
我們可以看到 Tornado Cash 簡單的兩個函式:Deposit 與 Withdraw,透過將代幣送入合約後再提領到另一個地址的流程,應用 ZKP 達成匿名的交易。
除了斷開 Deposit 與 Withdraw 的地址關聯性之外,Tornado Cash 還有做了一層「藏樹於林」的隱私防護,這部份的解釋就請參考 ZKP 讀書會 Tornado Cash。
網路上很多關於 ZKP 的文章或專案都是在 2019 年後出產的,經過許多人對這項技術的嘗試,讓我們對 ZKP 有了更清晰的理解,如今兩年後,開發工具也變得更加成熟,期待未來在 web 隱私議題上能看到更多 ZKP 大放異彩的應用。
原始碼
tornado-core
simple-tornado
參考資料
ZKP 讀書會 Tornado Cash
Tornado Privacy Solution Cryptographic Review
Tornado Cash 實例解析 was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
同時也有8部Youtube影片,追蹤數超過4萬的網紅吳老師教學部落格,也在其Youtube影片中提到,JAVA實用級解題分享之1(JAVA開發環境ECLIPSE設定與術科題目開啟) 這是在佛光大學資訊應用學系所講 JAVA入門證照的解題, 可以當成是學習JAVA的入門, 需要的是環境的設置與試題的理解, 學會這些題目,考不考證照就看自己了, 畢竟學會做出作品才是真的, 可以延伸到其他的設計需求, ...
「javascript 開發環境」的推薦目錄:
javascript 開發環境 在 Kewang 的資訊進化論 Facebook 的最佳解答
快來點我 👉👉👉 https://hahow.in/cr/kewang-backend 👈👈👈
大家好,小編這次籌備的新課「專為前端工程師準備的 Node.js 後端實戰課程」開始在 Hahow 好學校 上架募資啦!
在 2021/7/14 之前,在這篇文章按讚,並且公開分享這篇文章,及 tag 一位你的好朋友,除了可以用超優惠價格購買這門課程外,還有機會獲得 8 折的 coupon 喔!
---
這門課主要是從小編在這六七年來對於後端開發的集大成,以 Node.js+VS Code 做為開發環境。
會開這門課程的原因,主要是因為後端運用廣泛,但是門檻高、人才難找。而前端工程師經過了 MVVM 框架及 JavaScript 的洗禮後,再加上 Node.js 的流行,轉職到後端會比其他語言多了一層優勢。所以這門課程希望能讓已經有 JavaScript 基礎的前端工程師,也能輕鬆進入後端開發的大門。
課程內容主要是從 Express.js 開始著手,以 TODO list 做為貫穿整門課程的專案,其中可以學到許多內容,像是:
🔥 如何活用 package.json 及 dotenv 讓你快速開發
🔥 express.js 最重要的 middleware 開發及如何擴充 req/res
🔥 如何使用 Heroku 讓你快速部署網站上雲
🔥 如何使用 New Relic 來觀測網站運作狀況
其中也會教大家如何撰寫 API 文件及 RESTful API 的串接實戰,像是:
🔥 request 失敗到底要用 200 還是 400 回應
🔥 使用 mock server 快速串接 API
🔥 使用 Markdown 快速撰寫 API 文件
而資料庫則會搭配 MongoDB 及 Redis 做為快速開發使用:
🔥 MongoDB 的 schema 設計、CRUD 及最重要的 aggregate 使用方式
🔥 Redis 的 set/get 及 expire 功能簡易使用
---
這門課也有兩個募資解鎖單元,分別是「如何使用 Redis 開發 autocomplete 功能」、「如何使用 BullMQ 縮短 API 的回應時間」,歡迎大家踴躍報名這門課程,對課程有任何疑問都可以在課程網頁留言喔!
#nodejs #expressjs #javascript
javascript 開發環境 在 軟體開發學習資訊分享 Facebook 的最讚貼文
課程已於 2021 年 5 月更新
本課程將幫助你快速設定好開發環境與運行 React Native,並教你必需深入了解構建行動裝置React 元件的核心知識。
https://softnshare.com/the-complete-react-native-and-redux-course/
javascript 開發環境 在 吳老師教學部落格 Youtube 的最佳貼文
JAVA實用級解題分享之1(JAVA開發環境ECLIPSE設定與術科題目開啟)
這是在佛光大學資訊應用學系所講 JAVA入門證照的解題,
可以當成是學習JAVA的入門,
需要的是環境的設置與試題的理解,
學會這些題目,考不考證照就看自己了,
畢竟學會做出作品才是真的,
可以延伸到其他的設計需求,
如:
Android APP開發、JSP動態網頁、Servlet伺服器端的開發、
JavaScript、Jquery、Jquery Mobile、
其他C#的語法也和JAVA很類似。
完整教學:
https://www.youtube.com/playlist?list=PLgzs-Q3byiYMVnYJCPsbyaITTdYtPf8DG
部落格:
http://terry55wu.blogspot.tw/2014/01/javaandroid.html
01_JAVA開發環境與術科題目說明
02_開啟ECLIPSE與101題試題說明
03_101題解答01(產生7個號碼與輸出)
04_101題解答02(產生不重覆與除錯模式)
05_102題解答01(用Date類別產生日期時間)
JAVA證照考題解答分享(Android證照的跳板)
課程大綱:
1.認識 AWT類別
2.認識並學習如何建立視窗物件
3.學習如何管理與配置版面
4.事件處理:1.認識 Java的委派事件模式。2.認識並學習使用各種事件處理類別。3.學習各種物件的事件處理 。
之後:
1.分享最新的JAVA DOCS資訊與中文化版本,
並設定ECLIPSE直接讀取JAVA說明檔的設定方法。
2.利用實例綜合練習變數宣告、資料型別、運算子、
流程控制的IF...ELSE與各種迴圈方法的應用。
3.說明陣列與多維陣列的使用與實例。
漸漸更深入JAVA語法的核心,有些同學似乎已經吃不消,
但有些同學可能以前學過,所以一下子就解出來了,
也很大方的分享出他的解法,
不過這樣有時反而讓一些沒學過JAVA的同學備感壓力。
因為老師以為大家都會了,所以就加速往前,害一些同學在後面趕的很辛苦,
腦筋已經被迴圈給轉的頭昏,還沒弄懂題目,又要接下一題,
所以真有點兩難,好在助教的提醒,有稍放慢一點進度,
若有程度較好的同學,請些自行預息後面的課程,
或是先準備TQC JAVA的學術科考題好了,再不然好心一點,
充當一下老師的分身,幫忙同學一下,感謝!
101模擬樂透彩
102系統日期、時間顯示
103亂數排序器
104河洛之數
105陣列行列轉換
106數值過濾器
107求平均值
108九九乘法表
109面積與體積計算
110單字測驗
202利息計算
204期末考分數計算
206四則運算
208三角形邊長判斷
210字元搜尋器
302字體設定選擇器
304簡易繪圖板
306滑鼠感應視窗
308藝人音樂評等
310年齡計算
TQC JAVA實用級20題已經上完,準備開始講進階級的第三類10題,
但上進階級10題若是沒有 AWT類別的概念,恐怕很難接上第三類的 AWT視窗設計,
所以就在上進階級前,先給湜憶學員一些概念,可以不只在電腦證照考試受用,
在日後撰寫程式也可以更得心應手,JAVA工程師職缺很大,主要是人才培養不易,
要有好的培訓計畫,才能學的好又能有系統,才不致學的有挫折感,
這那上課方式,我也會將之有系統的轉換成雲端教學方式,在線上就可以學習,
並可以與老師隨時互動,得知學習進度與成效,
而這樣的方式已經很成功在各校電腦課程進行中,
從學員們的滿分成效就可以一窺端倪,要有效率又學的好真的不太容易,
很需要學習方法,上課無章法只會浪費時間與金錢,有效率有成果的學習才是王道,
快上完JAVA的進階級,期待每個學員都能順利取得 JAVA證照。
java下載,jdk,eclipse,java教學網站,java教學影片,java eclipse教學,eclipse 教學,java證照解答,AWT類別, 電腦證照
javascript 開發環境 在 吳老師教學部落格 Youtube 的最佳解答
JAVA實用級解題分享之1(JAVA開發環境ECLIPSE設定與術科題目開啟)
這是在佛光大學資訊應用學系所講 JAVA入門證照的解題,
可以當成是學習JAVA的入門,
需要的是環境的設置與試題的理解,
學會這些題目,考不考證照就看自己了,
畢竟學會做出作品才是真的,
可以延伸到其他的設計需求,
如:
Android APP開發、JSP動態網頁、Servlet伺服器端的開發、
JavaScript、Jquery、Jquery Mobile、
其他C#的語法也和JAVA很類似。
完整教學:
https://www.youtube.com/playlist?list=PLgzs-Q3byiYMVnYJCPsbyaITTdYtPf8DG
部落格:
http://terry55wu.blogspot.tw/2014/01/javaandroid.html
01_JAVA開發環境與術科題目說明
02_開啟ECLIPSE與101題試題說明
03_101題解答01(產生7個號碼與輸出)
04_101題解答02(產生不重覆與除錯模式)
05_102題解答01(用Date類別產生日期時間)
JAVA證照考題解答分享(Android證照的跳板)
課程大綱:
1.認識 AWT類別
2.認識並學習如何建立視窗物件
3.學習如何管理與配置版面
4.事件處理:1.認識 Java的委派事件模式。2.認識並學習使用各種事件處理類別。3.學習各種物件的事件處理 。
之後:
1.分享最新的JAVA DOCS資訊與中文化版本,
並設定ECLIPSE直接讀取JAVA說明檔的設定方法。
2.利用實例綜合練習變數宣告、資料型別、運算子、
流程控制的IF...ELSE與各種迴圈方法的應用。
3.說明陣列與多維陣列的使用與實例。
漸漸更深入JAVA語法的核心,有些同學似乎已經吃不消,
但有些同學可能以前學過,所以一下子就解出來了,
也很大方的分享出他的解法,
不過這樣有時反而讓一些沒學過JAVA的同學備感壓力。
因為老師以為大家都會了,所以就加速往前,害一些同學在後面趕的很辛苦,
腦筋已經被迴圈給轉的頭昏,還沒弄懂題目,又要接下一題,
所以真有點兩難,好在助教的提醒,有稍放慢一點進度,
若有程度較好的同學,請些自行預息後面的課程,
或是先準備TQC JAVA的學術科考題好了,再不然好心一點,
充當一下老師的分身,幫忙同學一下,感謝!
101模擬樂透彩
102系統日期、時間顯示
103亂數排序器
104河洛之數
105陣列行列轉換
106數值過濾器
107求平均值
108九九乘法表
109面積與體積計算
110單字測驗
202利息計算
204期末考分數計算
206四則運算
208三角形邊長判斷
210字元搜尋器
302字體設定選擇器
304簡易繪圖板
306滑鼠感應視窗
308藝人音樂評等
310年齡計算
TQC JAVA實用級20題已經上完,準備開始講進階級的第三類10題,
但上進階級10題若是沒有 AWT類別的概念,恐怕很難接上第三類的 AWT視窗設計,
所以就在上進階級前,先給湜憶學員一些概念,可以不只在電腦證照考試受用,
在日後撰寫程式也可以更得心應手,JAVA工程師職缺很大,主要是人才培養不易,
要有好的培訓計畫,才能學的好又能有系統,才不致學的有挫折感,
這那上課方式,我也會將之有系統的轉換成雲端教學方式,在線上就可以學習,
並可以與老師隨時互動,得知學習進度與成效,
而這樣的方式已經很成功在各校電腦課程進行中,
從學員們的滿分成效就可以一窺端倪,要有效率又學的好真的不太容易,
很需要學習方法,上課無章法只會浪費時間與金錢,有效率有成果的學習才是王道,
快上完JAVA的進階級,期待每個學員都能順利取得 JAVA證照。
java下載,jdk,eclipse,java教學網站,java教學影片,java eclipse教學,eclipse 教學,java證照解答,AWT類別, 電腦證照
javascript 開發環境 在 吳老師教學部落格 Youtube 的最佳貼文
JAVA實用級解題分享之1(JAVA開發環境ECLIPSE設定與術科題目開啟)
這是在佛光大學資訊應用學系所講 JAVA入門證照的解題,
可以當成是學習JAVA的入門,
需要的是環境的設置與試題的理解,
學會這些題目,考不考證照就看自己了,
畢竟學會做出作品才是真的,
可以延伸到其他的設計需求,
如:
Android APP開發、JSP動態網頁、Servlet伺服器端的開發、
JavaScript、Jquery、Jquery Mobile、
其他C#的語法也和JAVA很類似。
完整教學:
https://www.youtube.com/playlist?list=PLgzs-Q3byiYMVnYJCPsbyaITTdYtPf8DG
部落格:
http://terry55wu.blogspot.tw/2014/01/javaandroid.html
01_JAVA開發環境與術科題目說明
02_開啟ECLIPSE與101題試題說明
03_101題解答01(產生7個號碼與輸出)
04_101題解答02(產生不重覆與除錯模式)
05_102題解答01(用Date類別產生日期時間)
JAVA證照考題解答分享(Android證照的跳板)
課程大綱:
1.認識 AWT類別
2.認識並學習如何建立視窗物件
3.學習如何管理與配置版面
4.事件處理:1.認識 Java的委派事件模式。2.認識並學習使用各種事件處理類別。3.學習各種物件的事件處理 。
之後:
1.分享最新的JAVA DOCS資訊與中文化版本,
並設定ECLIPSE直接讀取JAVA說明檔的設定方法。
2.利用實例綜合練習變數宣告、資料型別、運算子、
流程控制的IF...ELSE與各種迴圈方法的應用。
3.說明陣列與多維陣列的使用與實例。
漸漸更深入JAVA語法的核心,有些同學似乎已經吃不消,
但有些同學可能以前學過,所以一下子就解出來了,
也很大方的分享出他的解法,
不過這樣有時反而讓一些沒學過JAVA的同學備感壓力。
因為老師以為大家都會了,所以就加速往前,害一些同學在後面趕的很辛苦,
腦筋已經被迴圈給轉的頭昏,還沒弄懂題目,又要接下一題,
所以真有點兩難,好在助教的提醒,有稍放慢一點進度,
若有程度較好的同學,請些自行預息後面的課程,
或是先準備TQC JAVA的學術科考題好了,再不然好心一點,
充當一下老師的分身,幫忙同學一下,感謝!
101模擬樂透彩
102系統日期、時間顯示
103亂數排序器
104河洛之數
105陣列行列轉換
106數值過濾器
107求平均值
108九九乘法表
109面積與體積計算
110單字測驗
202利息計算
204期末考分數計算
206四則運算
208三角形邊長判斷
210字元搜尋器
302字體設定選擇器
304簡易繪圖板
306滑鼠感應視窗
308藝人音樂評等
310年齡計算
TQC JAVA實用級20題已經上完,準備開始講進階級的第三類10題,
但上進階級10題若是沒有 AWT類別的概念,恐怕很難接上第三類的 AWT視窗設計,
所以就在上進階級前,先給湜憶學員一些概念,可以不只在電腦證照考試受用,
在日後撰寫程式也可以更得心應手,JAVA工程師職缺很大,主要是人才培養不易,
要有好的培訓計畫,才能學的好又能有系統,才不致學的有挫折感,
這那上課方式,我也會將之有系統的轉換成雲端教學方式,在線上就可以學習,
並可以與老師隨時互動,得知學習進度與成效,
而這樣的方式已經很成功在各校電腦課程進行中,
從學員們的滿分成效就可以一窺端倪,要有效率又學的好真的不太容易,
很需要學習方法,上課無章法只會浪費時間與金錢,有效率有成果的學習才是王道,
快上完JAVA的進階級,期待每個學員都能順利取得 JAVA證照。
java下載,jdk,eclipse,java教學網站,java教學影片,java eclipse教學,eclipse 教學,java證照解答,AWT類別, 電腦證照