consensys / anonymous-zether Goto Github PK
View Code? Open in Web Editor NEWA private payment system for Ethereum-based blockchains, with no trusted setup.
License: Other
A private payment system for Ethereum-based blockchains, with no trusted setup.
License: Other
occur some errors
[root@localhost anonymous-zether]# node packages/example/
Error: Node error: {"code":-32000,"message":"unknown account"}
at Function.validate (/home/hook/zether/anonymous-zether/node_modules/web3-providers/dist/web3-providers.cjs.js:117:18)
at HttpProvider._callee$ (/home/hook/zether/anonymous-zether/node_modules/web3-providers/dist/web3-providers.cjs.js:792:61)
at tryCatch (/home/hook/zether/anonymous-zether/node_modules/regenerator-runtime/runtime.js:45:40)
at Generator.invoke [as _invoke] (/home/hook/zether/anonymous-zether/node_modules/regenerator-runtime/runtime.js:271:22)
at Generator.prototype. [as next] (/home/hook/zether/anonymous-zether/node_modules/regenerator-runtime/runtime.js:97:21)
at asyncGeneratorStep (/home/hook/zether/anonymous-zether/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
at _next (/home/hook/zether/anonymous-zether/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
at processTicksAndRejections (internal/process/task_queues.js:85:5)
Hi,
When I execute node packages/example
, I have this error:
internal/modules/cjs/loader.js:800
throw err;
^
Error: Cannot find module 'BN.js'
I ran 7nodes through docker, modified the settings as required, and install prerequisites. Yarn runs fine
yarn install v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 45.05s.
Why all the transfer amounts have to be kept pending ?
describe from zether.pdf appendix D.1 Replay and double-spend protection
To make the design modular and better for future use. The component connecting node and java proof generation server in the zether-wallet should be easily reused. A good way would be packing it into NPM package. anonymous-zether would be only focused on an out-of-box tracker.js
should be updated to
var CLn = result.map((simulated, i) => bn128.serialize(bn128.unserialize(simulated[0][0]).add(L[i])));
var CRn = result.map((simulated) => bn128.serialize(bn128.unserialize(simulated[0][1]).add(R)));
I am trying to execute packages/example but it is failing while transferring the tokens from alice to bob.
The error is transaction reverted. What am i supposed to do?
Encountering a new bug here when trying to transfer with larger anonsets:
> Transfer failed: Error: Connection error: Couldn't write on the socket with Socket.write(payload)
(node:21874) UnhandledPromiseRejectionWarning: Error: Connection error: Couldn't write on the socket with Socket.write(payload)
at /Users/benediamond/anonymous-zether/node_modules/web3-providers/dist/web3-providers.cjs.js:636:23
at new Promise (<anonymous>)
at IpcProvider.sendPayload (/Users/benediamond/anonymous-zether/node_modules/web3-providers/dist/web3-providers.cjs.js:619:14)
at IpcProvider._callee$ (/Users/benediamond/anonymous-zether/node_modules/web3-providers/dist/web3-providers.cjs.js:185:29)
at tryCatch (/Users/benediamond/anonymous-zether/node_modules/regenerator-runtime/runtime.js:45:40)
at Generator.invoke [as _invoke] (/Users/benediamond/anonymous-zether/node_modules/regenerator-runtime/runtime.js:271:22)
at Generator.prototype.<computed> [as next] (/Users/benediamond/anonymous-zether/node_modules/regenerator-runtime/runtime.js:97:21)
at asyncGeneratorStep (/Users/benediamond/anonymous-zether/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
at _next (/Users/benediamond/anonymous-zether/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
at /Users/benediamond/anonymous-zether/node_modules/@babel/runtime/helpers/asyncToGenerator.js:32:7
(node:21874) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)
Not only is this not good, but it also wreaks havoc on the callback / balance adjustment process, and causes the node process to hang.
It would appear that this is an upstream bug in web3
, so I'm going to hold off for a bit and try to see what's going on. Hopefully no changes on our end will be necessary.
I've trying the example against a local Geth node but the transfer from Alice to Bob keeps failing in ZetherVerifier
with reason Recovery failure for B^x * A.
Any ideas on what I'm doing wrong?
I can move what I'm doing into a public repo if it helps, but I'm essentially following the example of Alice depositing into the Anonymous Zether contract and then transferring to Bob.
Using macOS, node and yarn versions as indicated in the prerequisites.
transfer test fals with output:
4 passing (13s)
1 failing
Hi, there ,
Mentioned in README.md, "The reason is that Raft reports block time differently (in nanoseconds, as opposed to milliseconds), an idiosyncrasy which interferes with epoch measurements."
---- Does it mean that if the block timestamp is changed to milliseconds, can it support zether?
How to understand code logic, there are too few comments
When i run truffle test
, i got:
Contract: ZSC
should allow transferring:
Uncaught TypeError: Cannot read property 'forEach' of null
at Subscription. (anonymous-zether/packages/anonymous.js/src/client.js:52:47)
and
Contract: ZSC
"after each" hook: after test for "should allow transferring":
Uncaught TypeError: Cannot read property 'forEach' of null
at Subscription. (anonymous-zether/packages/anonymous.js/src/client.js:52:47)
First of all, awesome work !!
Utils.readBalance is a loop from 0 to MAX_NUMBER in order to find the number that verifies the elliptic curve equation accumulator.eq(gB)
. Can a binary search be implemented to reduce the time complexity from O(N) down to O( log2 MAX_NUMBER), where is N encoded balance? Instead of using BN with Red, we can calculate the numbers with plain BN. Later we can use binary search to iterate identifying the solution i
that satisfies the balance.
Is it possible?
Is there a version of the contracts that uses ECADD
and ECMUL
implemented in EIP-1108?
rt
I am able to deploy the Utils.sol but can't deploy https://github.com/jpmorganchase/anonymous-zether/blob/master/packages/protocol/contracts/ZetherVerifier.sol and getting {"code":-32000,"message":"exceeds block gas limit"}
even I put 30 ethers as the gas fee. Any idea? Thanks
Example WorkflowTransaction Creation:The user creates a transaction using their private key. The transaction includes the destination address and the amount, but these are encrypted using zk-SNARKs or zk-STARKs.Proof Generation:Generate a zero-knowledge proof that the transaction is valid without revealing the sender, recipient, or amount.Transaction Submission:The transaction and proof are submitted to the Ethereum network. The network verifies the proof and, if valid, processes the transaction without knowing the details.Mixing:The transaction can be sent to a mixer to further obfuscate the origin. The mixer uses zero-knowledge proofs to ensure that funds are not stolen or lost during the mixing process.Confidentiality:Use confidential transaction techniques to hide the transaction amounts. This can be done through cryptographic commitments that allow for verification without revealing the actual amounts.Layer 2 Execution:Execute the transaction on a Layer 2 solution to increase efficiency and reduce gas costs. Only the final state is committed to the Ethereum mainnet, ensuring privacy and scalability.Implementation ConsiderationsSmart Contracts: Develop smart contracts that handle transaction processing, proof verification, and mixing. These contracts must be thoroughly audited to ensure security and correctness.User Experience: Create user-friendly interfaces and wallets that simplify the process of creating, submitting, and verifying transactions.Regulatory Compliance: Ensure that the system complies with relevant regulations, which may vary depending on the jurisdiction.Tools and LibrariesCircom: A circuit compiler that can be used to generate zk-SNARKs.ZoKrates: A toolbox for zk-SNARKs on Ethereum.Tornado Cash: An example of a mixer that can be adapted or extended.OpenZeppelin: Provides secure smart contract templates and libraries.zkSync: A Layer 2 scaling solution using zk-Rollups.
Hi @benediamond,
First of all, thank you for your hard work.
I found an error whenever I executed node packages/example
_Event {
type: 'error',
isTrusted: false,
_yaeti: true,
target: W3CWebSocket {
_listeners: {},
addEventListener: [Function: _addEventListener],
removeEventListener: [Function: _removeEventListener],
dispatchEvent: [Function: _dispatchEvent],
_url: 'ws://localhost:23000',
_readyState: 3,
_protocol: undefined,
_extensions: '',
_bufferedAmount: 0,
_binaryType: 'arraybuffer',
_connection: undefined,
_client: WebSocketClient {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
config: [Object],
_req: null,
protocols: [],
origin: undefined,
url: [Url],
secure: false,
base64nonce: 'DJABgcYI/AyqtmFRc2umRw=='
},
onerror: [Function],
onclose: [Function],
onmessage: [Function],
onopen: [Function]
},
cancelable: true,
stopImmediatePropagation: [Function]
}
I thought it was related to ws
configuration, but I couldn't evaluate it. Here is my modified istanbul-start.sh. I have added ws ports on geth instances.
I require "client.js" in my file like README.md
path = require('path'); const Client = require(path.join(__dirname, '../anonymous.js/src/client.js'));
but I get error
/home/hs_dev/solidity/anonymous-zether/packages/anonymous.js/src/utils/algebra.js:8
static base = {
^
SyntaxError: Unexpected token =
at Module._compile (internal/modules/cjs/loader.js:723:23)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (/home/tqxd/hs_dev/solidity/anonymous-zether/packages/anonymous.js/src/client.js:5:21)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
please help me
Hi,
when I finished 'truffle migrate' and entered the console, I tried to require the client.js but it turned out this error:
truffle(ganache)> exec ./client.js
Using network 'ganache'.
TypeError: Class constructor Client cannot be invoked without 'new'
at Object.exec (/usr/lib/node_modules/truffle/build/webpack:/packages/require/require.js:124:1)
at Environment.detect.then (/usr/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/exec.js:89:1)
at
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
May I ask how to fix that? how to import the client.js properly? (I run the protocol on ganache)
Thanks!
Please add a license to this project.
It seems other projects in this organization use the GNU Lesser General Public License v3.0
. Consider using that.
Hi,
I would like to appreciate your hard work for Anonymous Zether Protocol.
I am studying and trying to understand anon zether for a use-case and would like your comments. The use-case is a marketplace where items could be traded by sending anon zether from one user to another.
However, the marketplace itself needs a fee (flat per transaction). At this moment, your implementation is ignoring (or has not implemented) the fee structure and as such is unsuitable for marketplace idea and probably main-net block-chain protocols. Please note, fees is also a requirement to enable anon zether on a block-chain (or as a native token). So it is definitely a design requirement.
AFAIK, Fees needs to be open, verifiable, un-cheatable.
I am exploring different ideas but would like your comments on the best method to implement such a functionality without lowering security.
The ideas i am evaluating
Basically, its an enhancement to the protocol to support fees.
Thanks for your help from the bottom of my heart.
I am not sure if this is a truffle5 problem or something else. truffle migrate
cannot successfully deploy ZSC even after I deployed contracts step-by-step with asynchronous call.
@benediamond I have put my changes in branch. Please help test it out.
Hi there
Recently I tried to fork this project and to understand its mechanism, I've tried to test it on the Rinkeby test network.
Every single time I try to run the test script, I face this error:
Using network 'rinkeby'.
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Contract: ZSC
1) "before all" hook: prepare suite
0 passing (2m)
1 failing
1) Contract: ZSC
"before all" hook: prepare suite:
Error: Timeout of 120000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
I wonder if there is anyone who knows the reason for this error?
And whether this project is completed, or still under development?
I see that the deployment of the contracts is very expensive in gas. It is soo expensive that it is not even possible on the Ropsten test net without changing the gas limit for the block.
One optimization I am thinking about is to pre-compute constructors' data and store in as const memory in the Ethereum contracts once. Both contracts Burner and Verifier use the same computed data, so importing one pre-computed data should do the trick reducing it substantially.
The for iterates 64 times
https://github.com/jpmorganchase/anonymous-zether/blob/7ff65297422f0bed52dd18daa1318755178f975d/packages/protocol/contracts/ZetherVerifier.sol#L81-L88
If you find it helpful, I can do a pull request
I test index.js on the Ethereum using Tendermint, the codes of Ethereum just be updated two months ago(not entirely, the TxPool is kept old version), and we add some our own codes.
As the files in anonymous-zether, I only modify three files,
const Web3 = require("web3");
const Client = require("../anonymous.js/src/client.js");
const ZSC = require("../contract-artifacts/artifacts/ZSC.json");
const zv = require("../contract-artifacts/artifacts/ZetherVerifier.json");
const Deployer = require('./deployer.js');
const Provider = require('./provider.js');
const utils = require('../anonymous.js/src/utils/utils.js');
const run = async () => {
var provider = new Provider("ws://127.0.0.1:8546");
const web3 = new Web3(await provider.getProvider());
const accounts = await web3.eth.getAccounts();
const web3Http = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"))
await web3Http.eth.personal.unlockAccount(accounts[0], '123')
await web3Http.eth.personal.unlockAccount(accounts[3], '123')
await web3Http.eth.personal.unlockAccount(accounts[4], '123')
await web3Http.eth.personal.unlockAccount(accounts[5], '123')
var deployer = new Deployer(accounts);
const [
cash, [zether, burn]
] = await Promise.all([deployer.deployCashToken().then((result) => result.contractAddress), deployer.deployInnerProductVerifier().then((result) => {
console.log('deployer', result)
ip = result.contractAddress;
return Promise.all([deployer.deployZetherVerifier(ip), deployer.deployBurnVerifier(ip)]).then((results) => results.map((result) => result.contractAddress));
})]);
const zsc = await Promise.all([deployer.deployZSC(cash, zether, burn, 10), deployer.mintCashToken(cash, 1000)]).then((results) => results[0].contractAddress);
await deployer.approveCashToken(cash, zsc, 1000);
const deployed = new web3.eth.Contract(ZSC.abi, zsc);
const deployedZether = new web3.eth.Contract(zv.abi, zether);
const alice = new Client(web3, deployed, accounts[0], deployedZether);
await alice.register();
await alice.deposit(100);
const bob = new Client(web3, deployed, accounts[3]);
await bob.register();
alice.friends.add("Bob", bob.account.public());
const Billy = new Client(web3, deployed, accounts[4]);
const Jack = new Client(web3, deployed, accounts[5]);
await Billy.register();
await Jack.register();
alice.friends.add("Billy", bob.account.public());
alice.friends.add("Jack", bob.account.public());
await alice.transfer('Bob', 11, ["Billy", "Jack"]);
await alice.withdraw(10);
await alice.transfer('Bob', 10);
};
run().catch(console.error);
and I add two more clients, as the decoys in the Alice transfer to Bob case, and I let the case run first, after Alice deposits 100 and before Alice withdraw 10.
var throwaway = web3.eth.accounts.create();
var encoded = zsc.methods.transfer(C, D, y, u, proof).encodeABI();
var tx = { 'to': zsc._address, 'data': encoded, 'gas': 54700000, 'nonce': 0 , 'gasPrice': 0 };
web3.eth.accounts.signTransaction(tx, throwaway.privateKey).then((signed) => {
web3.eth.sendSignedTransaction(signed.rawTransaction)
.on('transactionHash', (hash) => {
I add 'gasPrice': 0 , otherwise the new account has no money to do the transaction.
Then I found the transfer with decoys fail in certain probability, about 1/3 failure rate.
/usr/local/bin/node /home/james/zether/anonymous-zether/packages/example/index.js
Debugger listening on ws://127.0.0.1:38651/d6d62edc-c959-4061-b011-a2973a03732f
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
Cash token contact mined (address = "0x06AB432cA0F676184E12a7BB5c5E4194E6eCCD87").
Inner product verifier mined (address = "0x5cC3cac7ED20A674B933c0D5D34ab96117aDed04").
deployer {
blockHash: '0xcf3cbaca2b620b0b728bee91c85b4f2ab6d877a17d562b54c3c3a27c974f5661',
blockNumber: 4229,
contractAddress: '0x5cC3cac7ED20A674B933c0D5D34ab96117aDed04',
cumulativeGasUsed: 6369585,
from: '0x8423328b8016fbe31938a461b5647de696bdbf71',
gasUsed: 4767225,
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
status: true,
to: null,
transactionHash: '0x2a610caf7e4689beaa59b1059aefbfe076c1bbb3cd19a44b1685b323b7713d08',
transactionIndex: 1,
events: {}
}
Burn verifier mined (address = "0x70304100B87aAB723C51A6ea6CDFfDdfD20f5f66").
Zether verifier mined (address = "0x15c9F2C1CB945924d4B16aF9894c6d2875A6d87E").
ERC20 funds minted (balance = 1000).
ZSC main contract deployed (address = "0xCC5836f96Ad578F145730693faa67896215C24e1").
ERC funds approved for transfer to ZSC (allowance = 1000).
Registration submitted (txHash = "0x25e3e22cbeb16d264ffc8cd3d7b99a0c1e974c19979b27b980f53da04a5bab8e").
Registration successful.
Initiating deposit.
Deposit submitted (txHash = "0x8f730e2f641e4ba9e5b64fc2ce8c163fad5db84d7208e4da85b0510a1118ec62").
Deposit of 100 was successful. Balance now 100.
Registration submitted (txHash = "0x81bda515ba733a10b8b635630ce81265adeff27ec6c4f208d0def89a0690feb1").
Registration successful.
Registration submitted (txHash = "0xef302858d28b7b6d9868e7ea673901e11ffda4dbf2710d6555538943199fd0f2").
Registration successful.
Registration submitted (txHash = "0x7cb3d43732f26fef7c5668ebb4aa3f41dc30098909dffde05885f2aa6654434e").
Registration successful.
======transfer! experiment begin
======transfer! experiment end
Transfer submitted (txHash = "0x1ac371c4dd8a707a5eb29dcc36cee4b4d31916c067a93baaba287317c5c4bcf0").
Transfer failed: Error: Transaction has been reverted by the EVM:
{
"blockHash": "0xa5deac094ac0b04d186bc2f2a83f9e0856d49424450199a7cbeae8e934fbd14a",
"blockNumber": 4239,
"contractAddress": null,
"cumulativeGasUsed": 53861975,
"from": "0x23c389f07438369f8731ee3230fe6a4014c2344d",
"gasUsed": 53861975,
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": false,
"to": "0x15c9f2c1cb945924d4b16af9894c6d2875a6d87e",
"transactionHash": "0x1ac371c4dd8a707a5eb29dcc36cee4b4d31916c067a93baaba287317c5c4bcf0",
"transactionIndex": 0
}
Error: Transaction has been reverted by the EVM:
{
"blockHash": "0xa5deac094ac0b04d186bc2f2a83f9e0856d49424450199a7cbeae8e934fbd14a",
"blockNumber": 4239,
"contractAddress": null,
"cumulativeGasUsed": 53861975,
"from": "0x23c389f07438369f8731ee3230fe6a4014c2344d",
"gasUsed": 53861975,
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": false,
"to": "0x15c9f2c1cb945924d4b16af9894c6d2875a6d87e",
"transactionHash": "0x1ac371c4dd8a707a5eb29dcc36cee4b4d31916c067a93baaba287317c5c4bcf0",
"transactionIndex": 0
}
at Object.TransactionError (/home/james/zether/anonymous-zether/node_modules/web3-core-helpers/src/errors.js:96:21)
at Object.TransactionRevertedWithoutReasonError (/home/james/zether/anonymous-zether/node_modules/web3-core-helpers/src/errors.js:108:21)
at /home/james/zether/anonymous-zether/node_modules/web3-core-method/src/index.js:482:48
at processTicksAndRejections (internal/process/task_queues.js:85:5) {
receipt: {
blockHash: '0xa5deac094ac0b04d186bc2f2a83f9e0856d49424450199a7cbeae8e934fbd14a',
blockNumber: 4239,
contractAddress: null,
cumulativeGasUsed: 53861975,
from: '0x23c389f07438369f8731ee3230fe6a4014c2344d',
gasUsed: 53861975,
logs: [],
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
status: false,
to: '0x15c9f2c1cb945924d4b16af9894c6d2875a6d87e',
transactionHash: '0x1ac371c4dd8a707a5eb29dcc36cee4b4d31916c067a93baaba287317c5c4bcf0',
transactionIndex: 0
}
}
Hello, this release is great for anonymous Ether transactions but does not encrypt token transfers or - more abstractly - smart contract execution. EY Nightfall encrypts token transfers to a degree, but does not encrypt Ether transactions.
EY Nightfall can encrypt Ether transactions by merely creating wrapped Ether, WETH and using it as an ERC20 token.
This would still be a hurdle as these additional steps make it tricky for adoption, as just funding the initial addresses with Ether for gas could expose a lot. And doing that funding with this Zether seems to be a high barrier too.
A one and done solution would be great. Just food for thought, feel free to close this issue, or promote a discussion.
I just cloned the repo and I am running into an issue where all the tests aren't running successfully. The first 4 tests pass, but the rest of them fail, which involve a transfer. I am hoping to extend this project to be able to send multiple payments at once and also schedule payments in the future.
As the title says, is it possible to run this on Goerli testnet ?
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.