tornadocash / tornado-core Goto Github PK
View Code? Open in Web Editor NEWTornado cash. Non-custodial private transactions on Ethereum.
Home Page: https://tornado.cash
License: GNU General Public License v3.0
Tornado cash. Non-custodial private transactions on Ethereum.
Home Page: https://tornado.cash
License: GNU General Public License v3.0
There are a lot of people depositing 32 ETH as a validator for the beaconchain. It would be great if these users would have a quick and easy way to deposit/withdraw 32.1 ETH from/to tornado.cash.
I've been trying to run ./cli.js test this command after setting up ganache and contract deployment. (followed all instructions)
However, I kept having execution revert error. Do you have any idea why?
The node version is v11.15.0
Start performing ETH deposit-withdraw test
Your note: tornado-eth-0.1-1337-0xad6cde8d27dce687045de2664045a286d94f58358c2068f550e27c32c4943ff134b2825b8436cb9d3ac888fcdfed5f44f328ff6365a2c2e5d334c2c61067
Tornado ETH balance is 0
Sender account ETH balance is 99.7440541
Submitting deposit transaction
Tornado ETH balance is 0.1
Sender account ETH balance is 99.62427308
Getting current state from tornado contract
Generating SNARK proof
Proof time: 15864.924ms
Submitting withdraw transaction
Error: Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof
at Object.ErrorResponse (/Users/seoyoungko/github/tornado-core/node_modules/web3-core-helpers/src/errors.js:29:16)
at /Users/seoyoungko/github/tornado-core/node_modules/web3-core-requestmanager/src/index.js:140:36
at XMLHttpRequest.request.onreadystatechange (/Users/seoyoungko/github/tornado-core/node_modules/web3-providers-http/src/index.js:102:13)
at XMLHttpRequestEventTarget.dispatchEvent (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:22)
at XMLHttpRequest._setReadyState (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request.js:208:14)
at XMLHttpRequest._onHttpResponseEnd (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request.js:318:14)
at IncomingMessage. (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request.js:289:61)
at IncomingMessage.emit (events.js:198:15)
at endReadableNT (_stream_readable.js:1139:12)
at processTicksAndRejections (internal/process/task_queues.js:81:17)
At @tornadocash/tornado-core/blob/master/contracts/ERC20Tornado.sol
(line 51).
It is supposed the user has to approve the tornado contract to perform the transfer from the user to "this" tornado contract address, at calling the token's contract. So the user has to spend the referred gas amount anyway.
Why don't include the step inside the "_processDeposit()" function?:
Something like:
function _safeErc20TransferFrom(address _from, address _to, uint256 _amount) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, _to, _amount));
require(success, "not enough funds");
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd /* transferFrom */, _from, _to, _amount));
require(success, "not enough allowed tokens");
// if contract returns some data lets make sure that is `true` according to standard
if (data.length > 0) {
require(data.length == 32, "data length should be either 0 or 32 bytes");
success = abi.decode(data, (bool));
require(success, "not enough allowed tokens. Token returns false.");
}
}
would this action implies any safety risk?
thanks!
Hi,
I just want to ask for some help.
Long story short,
I tried to do mixing on a Tornado Cash Fork in BSC, namely Jumble Cash.
Their website has been running smoothly, until one day, when I tried to use it again, it doesn't work.
My initial diagnosis, is that, maybe their servers, where circuits are hosted are down.
Additional Details: They mentioned that they are using their private nodes.
Check out: A Fork is not just a Fork
Is it possible to run my own environment, and still retrieve my funds?
I still have my withdrawal key (note) tho.
Thank you!
Tornado.cash makes connections to these domains:
tornado.cash
ethgasstation.info
fairish.net
fonts.googleapis.com
infura.io
kovan.website
mainnet-frelay.duckdns.org
nyuels.de
poa.network
us.to
youtube.com
zoltu.io
This is quite a lot for a service that is meant to preserve privacy, especially with the inclusion of Googleapis and Youtube. It damages the anonymity sets. It would be good to remove as many of these as possible and connect to the rest with your server, as far as it increases user privacy.
I have tried using Frame and Metamask to claim my TORN vouchers and both pop up errors when I try:
This leads me to think the issue is on the Tornado side rather than an issue with the wallets. Anyone know what the problem is here and how to solve it?
Edit: It may be useful to know when you are debugging this error that I am using a Ledger Nano S with Frame and Metamask.
Hello,
Just out of curiosity, i want to ask, why the need to generate proof first, before a user can confirm withdrawal, if we'd still need to check for a valid proof when trying to process withdrawal in smart contract?
Why not do every thing in just one process since the withdraw function will throw for invalid proof?
I have set up the Browser Version from this code. but Withdraw is not working getting
https://kovan.etherscan.io/tx/0x99410565af3c0302a975f2964f2291f32ecfe1ddb0fa7a7b3f8dedb8c4985b38
Fail with error 'Invalid withdraw proof'
Any help will be appreciated.
Instead of doing the MerkleTree computation onchain, it can be done offchain, and proved the correctness inside a zkSNARK proof.
This means that with the current approach (MerkleTree onchain) it needs 1M gas
for the deposit, while with this new approach (MerkleTree offchain + zkproof of correctness) in the tests that I did the gast cost is arround 0.3M gas
. This is thanks to the fact that the MerkleTree is moved to offchain computation and then proved its correctness inside the snark proof which is much cheaper to verify in the smart contract. (The withdraw continues very similar as it is now, as it is already with a zkproof verified in the contract).
I've made a proof of concept that works here: https://github.com/arnaucube/miksi-core ,
that can be tried here: https://arnaucube.github.io/miksi-app/ (still needs some improvements, but it works and can be currently used in Göerli testnet).
A bit of more detailed explaination:
All computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract
secret
& nullifier
commitment
, which is the hash: commitment = H(secret, nullifier, extradata)
commitment
into the MerkleTreesecret
& nullifier
for the commitment
which is in a leaf in the merkletreeRootOld
(the current one in the Smart Contract) to RootNew
has been done following the rules (only one leaf addition, no leaf deletion, correct leaf format, etc)deposit
call, together with the zkProof dataAll computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract
commitment
of which the user knows the secret
& nullifier
secret
for a public nullifier
commitment
is in the MerkleTreeroot
is the one that knows the SmartContractThe proposal would be then, to move the MerkleTree computation offchain, and instead of building the MerkleTree in Solidity, could be done in the client side, and then proved its corretness inside the zk-proof.
Hi, I've been trying to run ./cli.js test
this command after setting up ganache and contract deployment. (followed all instructions)
However, I kept having execution revert error. Do you have any idea why?
The node version is v11.15.0
Start performing ETH deposit-withdraw test
Your note: tornado-eth-0.1-1337-0xad6cde8d27dce687045de2664045a286d94f58358c2068f550e27c32c4943ff134b2825b8436cb9d3ac888fcdfed5f44f328ff6365a2c2e5d334c2c61067
Tornado ETH balance is 0
Sender account ETH balance is 99.7440541
Submitting deposit transaction
Tornado ETH balance is 0.1
Sender account ETH balance is 99.62427308
Getting current state from tornado contract
Generating SNARK proof
Proof time: 15864.924ms
Submitting withdraw transaction
Error: Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof
at Object.ErrorResponse (/Users/seoyoungko/github/tornado-core/node_modules/web3-core-helpers/src/errors.js:29:16)
at /Users/seoyoungko/github/tornado-core/node_modules/web3-core-requestmanager/src/index.js:140:36
at XMLHttpRequest.request.onreadystatechange (/Users/seoyoungko/github/tornado-core/node_modules/web3-providers-http/src/index.js:102:13)
at XMLHttpRequestEventTarget.dispatchEvent (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:22)
at XMLHttpRequest._setReadyState (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request.js:208:14)
at XMLHttpRequest._onHttpResponseEnd (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request.js:318:14)
at IncomingMessage.<anonymous> (/Users/seoyoungko/github/tornado-core/node_modules/xhr2-cookies/dist/xml-http-request.js:289:61)
at IncomingMessage.emit (events.js:198:15)
at endReadableNT (_stream_readable.js:1139:12)
at processTicksAndRejections (internal/process/task_queues.js:81:17)
Could you deploy a Tor hidden service (preferably version 3) so that Tornado is reachable via an onion address? This would make the transfer layer less prone to surveillance and through that increase the quality of the anonymity sets.
Hello,
Thank you for a great tool! I'm trying to figure out with the white paper and its bit unclear at the withdrawal section:
• Send a request to Relayer supplying transaction data R, h, A, f, t, P. The Relayer is then
supposed to make a transaction to contract C with supplied data.
It's not clear, why t (relayer's address) should be provided, isn't relayer knows own address?
Thank you!
Recommend upgrading to a LTS release.
When following the instructions to get set up and run tests (on node v11.15.0
):
npm install
cp .env.example .env
npm run build
npx ganache-cli
npm run test
I get the following:
ETHTornado's address 0x5A8C0aa42ED9907dE855BA3Bb0DeF21C6e8a5247
ERC20Tornado's address 0xAE6C63F4003C3A1277fA97A2808D9c27314720BD
TypeError: Cannot read property 'Fr' of undefined
at Object.<anonymous> (/Users/kevinho/Documents/Optimism/OptimisticRollup/tornado-core/node_modules/circomlib/src/poseidon.js:5:17)
at Module._compile (internal/modules/cjs/loader.js:816:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
at Module.load (internal/modules/cjs/loader.js:685:32)
at Function.Module._load (internal/modules/cjs/loader.js:620:12)
at Module.require (internal/modules/cjs/loader.js:723:19)
at require (internal/modules/cjs/helpers.js:14:16)
at Object.<anonymous> (/Users/kevinho/Documents/Optimism/OptimisticRollup/tornado-core/node_modules/circomlib/src/smt_hashes_poseidon.js:1:18)
at Module._compile (internal/modules/cjs/loader.js:816:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
at Module.load (internal/modules/cjs/loader.js:685:32)
at Function.Module._load (internal/modules/cjs/loader.js:620:12)
at Module.require (internal/modules/cjs/loader.js:723:19)
at require (internal/modules/cjs/helpers.js:14:16)
at Object.<anonymous> (/Users/kevinho/Documents/Optimism/OptimisticRollup/tornado-core/node_modules/circomlib/src/smt.js:4:24)
at Module._compile (internal/modules/cjs/loader.js:816:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
at Module.load (internal/modules/cjs/loader.js:685:32)
at Function.Module._load (internal/modules/cjs/loader.js:620:12)
at Module.require (internal/modules/cjs/loader.js:723:19)
at require (internal/modules/cjs/helpers.js:14:16)
at Object.<anonymous> (/Users/kevinho/Documents/Optimism/OptimisticRollup/tornado-core/node_modules/circomlib/index.js:1:15)
at Module._compile (internal/modules/cjs/loader.js:816:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
at Module.load (internal/modules/cjs/loader.js:685:32)
at Function.Module._load (internal/modules/cjs/loader.js:620:12)
at Module.require (internal/modules/cjs/loader.js:723:19)
at require (internal/modules/cjs/helpers.js:14:16)
Got the error on another machine as well
In case of the proving system having an issue and needing an update (or to add new features), there is a function called updateVerifier
that can be invoked by the operator
.
tornado-core/contracts/Tornado.sol
Line 116 in cfaf325
This function should probably be time-locked, so someone who has the operator keys (potentially by thieving them) can't unilaterally change the proving system and find some way of stealing the funds.
In relayer/issues/13 I proposed a different relayer fee scheme that is non-rent-seeking:
relayerFeeOptimal
= gasLimitPromised
* gasPricePromised
* ( 1 + relayerFeeLevel
)
There is another problem with this scheme.
Upon withdrawal through a relayer, the GUI displays gasPricePromised
(e.g. 20 gwei) and the transaction fee part of the total relayerFeeCurrent
, from which we can calculate gasLimitPromised
(usually around 500 000 gas).
These are only promises, which are continuously broken by relayers. It's common to see the above values promised but the actual withdrawal being sent with a gas price of 10 gwei and a gas limit of 400 000 gas. Relayers are lying about what they charge fees for. I'd be curious why you allow this to happen, but the point of this proposal is to alter proof generation and relayer mechanics: when the user generates the proof with the withdrawal parameters they accepted, those parameters should be enforced through the proof as minimum values. The relayer would be free to submit the transaction with higher values if their lookout changes, but not lower, and only at their own expense.
The fee that is deducted from the would change to this:
relayerFeeHonest
= gasLimitMinimum
* gasPriceMinimum
* ( 1 + relayerFeeLevel
)
Withdrawal transactions would need to have at least this much gas limit and gas fee. If the chosen relayer changes their mind (e.g. sees heightened network utilization and fears the transaction will be stuck), they could submit with higher values (e.g. a higher gas price), but only by funding the extra cost from their own funds, as not to be able to deduct a greater fee than what the user agreed to.
This will force relayers to be honest about the fee level they operate with, bringing prices lower, attracting more users and ultimately increasing anonymity. If your real goal with Tornado is anonymity, I hope you will consider these changes.
Edit: corrected equations.
In ERC20Tornado's implementation, refund is forwarded to the recipient using _recipient.call
or, if that fails, returned to the relayer using _relayer.transfer
see:
tornado-core/contracts/ERC20Tornado.sol
Line 46 in a533ad9
I believe this will limit the ability of relayers to use smart contract accounts for relayer, which might not be an issue right now, but could be in the future. Any documentation on why this is not done using _relayer.call
?
No matter how many times I try and which relayer I choose, still getting the above error.
During withdrawal, it goes to the very end where it shows "Accepted" then finally this error.
I also noticed that the "recent deposit" entry is not present for this deposit in the Tornado Deposit UI perhaps because i switched to ETH network while the deposit transaction was midway. Right now the funds are locked for me!
Any assistance will be appreciated! Thanks!
Note: After using wallet for gas payment, this problem went away
swirl.cash is claiming to be a Tornado fork on Binance Smart Chain, but their GitHub is missing many of the key components such as the ZK circuits. I asked on their Telegram when they are going to fully publish their source and they said "soon".
Whether they are a legit project or a scam still remains to be seen IMHO, but in the meantime AFAICS they are currently violating Tornado.cash's GPL-3.0 license. For example, compare https://github.com/SwirlCash/SWIRL/blob/master/contracts/MerkleTreeWithHistory.sol with https://github.com/tornadocash/tornado-core/blob/master/contracts/MerkleTreeWithHistory.sol and then observe that https://github.com/SwirlCash/SWIRL does not contain any proper copyright or licensing declarations.
To me it looks like they've initialised a fresh OpenZeppelin project, then copy-pasted in a few bits of Tornado's smart contracts and done a search and replace to change any mentions of Tornado to Swirl. It begs the question: if they are a legit project, why wouldn't they have already published the full forked code base on GitHub? I found similar levels of obfuscation in their frontend code.
In case anyone reads this and wants to make the counter-claim that Swirl has already been audited and/or is safe because liquidity / tokens are locked in Wault Finance:
The default choice of relay usually calculates the transaction fee with 4x the gas price that would make sense for next-block inclusion, and charges 0.5-2% by volume. Meanwhile, other relays in the list are much cheaper and sensible. Also, the relay choice setting is quite well-hidden and most people never realize they have options, so they will just go along with the default offer, which is the most expensive of all.
This makes no sense from a price competitiveness standpoint, and questions your integrity. One can imagine a scenario where you have an cartel agreement with this relayer: you make them default, they rip off people and share the inflated income with you. Maybe it's time to prove this is not the case by always offering the cheapest reachable relayer and making the relayer choice setting more visible.
在 bsc 网络中存了 bnb 提取的时候一直提示 "错误 无法从合约中取得所有存款事件" 该错误!!
Trying to withdraw 1 eth using my note + metamask which fails and receiving the following error message 'TypeError: Cannot convert null to a BigInt'.
Submitting the note shows all the right details about the deposit, I then click withdraw, the 'generating proofs' loading screen shows, and the error shows up in the console, and in your UI under the recipient address field.
Can you please fix this so I can withdraw my funds?
This issue came up when swapping AP for TORN, and I saw more than 5 people in the community mention this issue.
I have tried these solutions:
But all didn't work.
I found that before swapping AP/TORN, the web page requests the RPC interface by method named eth_getLogs, with params:
[{ firstBlock: "0x00", ... }]
Maybe that is the reason for this issuse. Can we fixed it by changing the "firstBlock" to a bigger number ?
Hope for your help, please.
MetaMask is the most used web software wallet.
Please support it on https://tornado.cash.
After the transfer operation failed, I tried to backtrace its file (_proving_key.bin) but did not know from what file or what file it was generated,A file (descriptive _proving_key.bin) is converted in what way ?
tornado.cash cannot read the balance of eth in AlphaWallet
it is able to read the other balances like DAI etc but not eth.
This is what I get in the console
[Log] sendAsync, method, from, params – "eth_getBalance" – undefined – ["0x42ea529282DDE0AA87B42d9E83316eb23FE62c3f", "latest"] (2) (51304e939a3655ed1e6c.js, line 1)
The link to the whitepaper in the readme file is broken:
https://tornado.cash/Tornado.cash_whitepaper_v1.4.pdf
Please fix.
Similarly to how deposits are displayed for each note type, also display withdrawals to support the user in choosing an optimal withdrawal time.
In the whitepaper https://tornado.cash/audits/TornadoCash_whitepaper_v1.4.pdf at definition (1) the very bottom of page 1, "...And O is the opening of H2(r||k)" should read "...And O is the opening of H1(r||k)", changing the MiMC hash H2 to the Pederson hash H1.
In addition the definition (1) of the statement of knowledge S[R, h, A, f, t] does not bind the symbols A, f, and t -- leaving them undefined. Later in the whitepaper, they can be inferred to mean address, fee, and relayer, but I don't think the actual proof circuits need these values. S[R, h] would be more succinct.
I am creating a gitcoin bounty for the following. Linking to this issue.
Create a twitter bot that communicates how many new deposits have been made to the Tornado contract within a 24 hour window for ETH and Dai.
I am following the readme.md to run test bellows:
npm install
cp .env.example .env
npm run build - this may take 10 minutes or more
npx ganache-cli
npm run test
but it failed with error: Invalid withdraw proof
The proving_key in verifier sol
file and ERC20Tornado.test.js
is the same.
but the code returns false in https://github.com/tornadocash/tornado-core/blob/master/test/ETHTornado.test.js#L138
anyone have an idea where is the problem and how to fix this?
logs:
1) Contract: ERC20Tornado
#withdraw
should work:
Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof -- Reason given: Invalid withdraw proof.
at PromiEvent (node_modules/truffle/build/webpack:/packages/contract/lib/promievent.js:6:1)
at TruffleContract.withdraw (node_modules/truffle/build/webpack:/packages/contract/lib/execute.js:158:1)
at Context.<anonymous> (test/ERC20Tornado.test.js:169:86)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
2) Contract: ERC20Tornado
#withdraw
should return refund to the relayer is case of fail:
Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof -- Reason given: Invalid withdraw proof.
at PromiEvent (node_modules/truffle/build/webpack:/packages/contract/lib/promievent.js:6:1)
at TruffleContract.withdraw (node_modules/truffle/build/webpack:/packages/contract/lib/execute.js:158:1)
at Context.<anonymous> (test/ERC20Tornado.test.js:248:86)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
3) Contract: ERC20Tornado
#withdraw
should reject with wrong refund value:
AssertionError: expected 'Invalid withdraw proof' to equal 'Incorrect refund amount received by the contract'
+ expected - actual
-Invalid withdraw proof
+Incorrect refund amount received by the contract
at Context.<anonymous> (test/ERC20Tornado.test.js:313:24)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
4) Contract: ETHTornado
snark proof verification on js side
should detect tampering:
AssertionError: expected false to equal true
+ expected - actual
-false
+true
at Context.<anonymous> (test/ETHTornado.test.js:138:24)
5) Contract: ETHTornado
#withdraw
should work:
Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof -- Reason given: Invalid withdraw proof.
at PromiEvent (node_modules/truffle/build/webpack:/packages/contract/lib/promievent.js:6:1)
at TruffleContract.withdraw (node_modules/truffle/build/webpack:/packages/contract/lib/execute.js:158:1)
at Context.<anonymous> (test/ETHTornado.test.js:217:71)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
6) Contract: ETHTornado
#withdraw
should prevent double spend:
AssertionError: expected promise to be fulfilled but it was rejected with 'Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof -- Reason given: Invalid withdraw proof.'
7) Contract: ETHTornado
#withdraw
should reject with tampered public inputs:
AssertionError: expected promise to be fulfilled but it was rejected with 'Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof -- Reason given: Invalid withdraw proof.'
8) Contract: ETHTornado
#withdraw
should reject with non zero refund:
AssertionError: expected 'Invalid withdraw proof' to equal 'Refund value is supposed to be zero for ETH instance'
+ expected - actual
-Invalid withdraw proof
+Refund value is supposed to be zero for ETH instance
at Context.<anonymous> (test/ETHTornado.test.js:482:30)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
9) Contract: ETHTornado
#isSpent
should work:
Error: Returned error: VM Exception while processing transaction: revert Invalid withdraw proof -- Reason given: Invalid withdraw proof.
at PromiEvent (node_modules/truffle/build/webpack:/packages/contract/lib/promievent.js:6:1)
at TruffleContract.withdraw (node_modules/truffle/build/webpack:/packages/contract/lib/execute.js:158:1)
at Context.<anonymous> (test/ETHTornado.test.js:573:54)
npm ERR! code ELIFECYCLE
npm ERR! errno 9
npm ERR! [email protected] test: `npx truffle test`
npm ERR! Exit status 9
npm ERR!
npm ERR! Failed at the [email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/hao/.npm/_logs/2021-01-25T07_28_46_486Z-debug.log
Do you have any plan to replace with plonk?
I tried to obfuscate 0.1 kETH (in Kovan test network). I did my deposit using Brave browser, but I wanted to try a real life experience using TOR browser for the withdraw transaction.
On TOR browser it throws the "Web assembly is not defined" error, but when tried on Brave, "withdraw" successfully calculates the SNARK proof. Perhaps it is needed to upgrade NodeJs ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.