Giter Site home page Giter Site logo

paradigmxyz / alphanet Goto Github PK

View Code? Open in Web Editor NEW
125.0 9.0 26.0 1.28 MB

Reth AlphaNet is a testnet OP Stack-compatible rollup aimed at enabling experimentation of bleeding edge Ethereum Research.

License: Apache License 2.0

Rust 76.88% Makefile 11.85% Solidity 8.44% Dockerfile 2.83%

alphanet's Introduction

alphanet

MIT License Apache-2.0 License CI Status

What is Reth AlphaNet?

Reth AlphaNet is a testnet OP Stack rollup aimed at enabling experimentation of bleeding edge Ethereum Research. AlphaNet is not a fork of reth. AlphaNet implements traits provided by the reth node builder API, allowing implementation of precompiles and instructions of experimental EIPs without forking the node.

Specifically, AlphaNet currently implements the following EIPs:

  • EIP-3074: AUTH and AUTHCALL instructions.
  • EIP-7212: Precompile for secp256r1 curve support.
  • EIP-2537: Precompiles for BLS12-381 curve operations.

Why AlphaNet?

AlphaNet has 2 goals:

  1. Showcase Reth's performance at the extremes. We intend to launch a hosted version of AlphaNet on Conduit, targeting 50mgas/s, and eventually ramping up to 1ggas/s and beyond. In the process we hope to hit the state growth performance bottleneck, and discover ways to solve it. If our hosted chains end up getting too big, we may possibly restart the experiment from zero, and try again.
  2. Showcase how Reth's modular architecture can serve as a distribution channel for research ideas. Specifically, AlphaNet's node extensions were chosen for their ability to enable applications that enhance the onchain user experience, and drastically reduce cost for existing applications that improve UX.

AlphaNet Local Development

AlphaNet does not yet have a running testnet, but can be run locally for development and testing purposes. To do this, the binary can be run with the --dev flag, which will start the node with a development configuration.

First, alphanet should be built locally:

git clone https://github.com/paradigmxyz/alphanet
cd alphanet
cargo install --path bin/alphanet
alphanet node --chain etc/alphanet-genesis.json --dev --http --http.api all

This will start the node with a development configuration, and expose the HTTP API on http://localhost:8545.

To use 3074-enabled foundry, use eip-3074-foundry and follow installation instructions.

Running AlphaNet

⚠️ AlphaNet does not yet have a running testnet, please use the local development instructions above! ⚠️

Running AlphaNet will require running additional infrastructure for the archival L1 node. These instructions are a guide for running the AlphaNet OP-stack node only.

For instructions on running the full AlphaNet OP stack, including the L1 node, see the Reth book section on running the OP stack, using the alphanet binary instead of op-reth.

Running the alphanet execution node

To run AlphaNet from source, clone the repository and run the following commands:

git clone https://github.com/paradigmxyz/alphanet.git
cd alphanet
cargo install --path bin/alphanet
alphanet node
    --chain etc/alphanet-genesis.json \
    --rollup.sequencer-http <TODO> \
    --http \
    --ws \
    --authrpc.port 9551 \
    --authrpc.jwtsecret /path/to/jwt.hex

Running op-node with the alphanet configuration

Once alphanet is started, op-node can be run with the included alphanet-rollup.json:

cd alphanet/
op-node \
    --rollup.config ./etc/alphanet-rollup.json \
    --l1=<your-sepolia-L1-rpc> \
    --l2=http://localhost:9551 \
    --l2.jwt-secret=/path/to/jwt.hex \
    --rpc.addr=0.0.0.0 \
    --rpc.port=7000 \
    --l1.trustrpc

Security

See SECURITY.md.

Note on EIP-3074 integration tests

If you are modifying the EIP-3074 solidity smart contracts used in the alphanet-testing crate you should regenerate the built artifacts with:

$ make build-eip3074-bytecode

This command uses the docker image from the foundry-alphanet repo which contains patched versions of solc and forge compatible with the instructions introduced by EIP-3074.

The changes in the artifacts should be committed to this repo, this way we don't have to rely on docker being available to generate the artifacts and run the tests. There's a CI step that will check if the committed artifacts match the smart contracts source code.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

alphanet's People

Contributors

anna-carroll avatar danipopes avatar enitrat avatar fgimenez avatar github-actions[bot] avatar jxom avatar mattsse avatar rjected avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

alphanet's Issues

Bytecode generation for testing new instructions

We will want to add support for new instructions, for example AUTH and AUTHCALL from 3074: #5. To properly integration test these, we'll need some human readable example code that can be:

  • Converted into bytecode
  • Deployed, and finally
  • Tested

This is a chicken-and-egg problem: any new upgrade needs support in both the interpreter and the compiler to be properly integration tested.

One idea is extending eas (ethereum assembler) from etk:
https://github.com/quilt/etk

This is probably the quickest way to generating bytecode that can be deployed.

We could also look at past modifications to solc, and the 3074 fork of solc if we really want to fork solc:
EIP-3074: ethereum/solidity@develop...GregTheGreek:solidity:3074
EIP-7516 (BLOBBASEFEE): https://github.com/ethereum/solidity/pull/14755/files

The ideal compiler would allow us to:

  • Extend the evm with an instruction, for example BLOBBASEFEE
  • Layer this on top of any other modifications, for example an AUTH / AUTHCALL extension

without forking the compiler.

We'll need some test utils for generating bytecode, to make the unit tests relatively human-readable and concise.

Tracking: EIP Implementation

This issue tracks the existing EIPs we want to include in alphanet. This will grow over time

Alphanet EVM config

These can be implemented solely in the EVM trait implementation, following this example:
https://github.com/paradigmxyz/reth/blob/main/examples/custom-evm/src/main.rs

EIP-7212

Spec: https://eips.ethereum.org/EIPS/eip-7212

Example implementation:
https://github.com/alessandromazza98/revm/tree/eip-7212

This is a single precompile, so it will be used in the EVM config implementation

EIP-3074

Spec: https://eips.ethereum.org/EIPS/eip-3074

Implementation as foundry project with revm patches: https://github.com/anna-carroll/3074

This consists of two instructions, AUTH and AUTHCALL, also to be set in the EVM config implementation

Other EIPs

EIP-4337

This involves an alt mempool, requires extra infrastructure, and new RPC endpoints.

Alchemy has a reth-based bundler here: https://github.com/alchemyplatform/rundler

bug: `AUTHCALL` not conform to EIP-3074

  1. There is no gas stipend, even for non-zero value AUTHCALL

Sending non-zero value with CALL increases its cost by 9,000. Of that, 6,700 covers the increased overhead of the balance transfer and 2,300 is used as a stipend into the subcall to seed its gas counter. AUTHCALL does not provide a stipend and thus only charges the base 6,700.

  1. ethereum/EIPs@eca4416 modified the behavior of the AUTHCALL opcode to take 7 values from the stack, not 8. Following this update, AUTHCALL behaves like CALL, a few exceptions aside.

What needs to be changed :

  • Only 7 args are popped from the stack, not 8
  • value is deducted from the balance of authorized
  • no gas stipend should be added in case of value transfer.

Extract 3074 to a separate repo

EIP-3074 should be extracted to a separate repo so it can be decoupled from this codebase and potentially more easily removed once alphanet can support 7702 more easily.

3074 script transaction failure

Trying to run 3074-invokers's sendEth forge script example with this Docker build of foundry but I'm running into a Transaction failure error.

It shows a successful test simulation before broadcasting, but when it broadcasts to AlphaNet, the transaction fails. My thought is that there is a discrepancy between the way 3074 is implemented in the simulation build which is passing and AlphaNet which is failing. This error did not occur until after 3074-invokers's repo got updated to use foundry-alphanet for foundry things. Weirdly enough though, when running the sendEth forge script with the current version of foundry-alphanet on the Otim Devnet, it works...

Here is the output for reference:

julrach@julrach-s-mac 3074-invokers % make cmd="forge script Executor --sig sendEth(address,address,uint256) $INVOKER_ADDRESS 0x3074ca113074ca113074ca113074ca113074ca11 0.01ether --rpc-url $RPC_URL --broadcast -vvvv"
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Compiling 26 files with 0.8.24
Solc 0.8.24 finished in 1.77s
Compiler run successful with warnings:
Warning (3805): This is a pre-release compiler version, please do not use it in production.

Warning (2018): Function state mutability can be restricted to pure
  --> src/Auth.sol:43:5:
   |
43 |     function auth(bytes32 commit, Signature memory signature) public returns (bool success) {
   |     ^ (Relevant source part starts here and spans across multiple lines).

Warning (2018): Function state mutability can be restricted to pure
  --> src/Auth.sol:56:5:
   |
56 |     function authcall(address to, bytes memory data, uint256 value, uint256 gasLimit) public returns (bool success) {
   |     ^ (Relevant source part starts here and spans across multiple lines).

Traces:
  [54098] Executor::sendEth(0x5FbDB2315678afecb367f032d93F642f64180aa3, 0x3074Ca113074ca113074CA113074CA113074CA11, 10000000000000000 [1e16])
    ├─ [0] VM::addr(<pk>) [staticcall]
    │   └─ ← [Return] 0x29b7D9C8f9c4e158AeDC2bfC31D1931A519682Ed
    ├─ [2512] 0x5FbDB2315678afecb367f032d93F642f64180aa3::nextNonce(0x29b7D9C8f9c4e158AeDC2bfC31D1931A519682Ed) [staticcall]
    │   └─ ← [Return] 0
    ├─ [0] VM::addr(<pk>) [staticcall]
    │   └─ ← [Return] 0x29b7D9C8f9c4e158AeDC2bfC31D1931A519682Ed
    ├─ [0] VM::getNonce(0x29b7D9C8f9c4e158AeDC2bfC31D1931A519682Ed) [staticcall]
    │   └─ ← [Return] 0
    ├─ [1177] 0x5FbDB2315678afecb367f032d93F642f64180aa3::getDigest(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000055023074ca113074ca113074ca113074ca113074ca11000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 0) [staticcall]
    │   └─ ← [Return] 0xa5dde2dde74c211c6e9f4858203ea6c212807ecc05bfe495df0c20dd8bd64e22
    ├─ [0] VM::sign("<pk>", 0xa5dde2dde74c211c6e9f4858203ea6c212807ecc05bfe495df0c20dd8bd64e22) [staticcall]
    │   └─ ← [Return] 28, 0xa7d19736b0c8d7c143bc5ebb9f676c5207043ea918f78fcc339e5496ed3c285a, 0x0f86e650a01a9a6555917fc44ec3a87a3f53dc471fb63ec6dc94efc1d6b3b78e
    ├─ [0] VM::startBroadcast(<pk>)
    │   └─ ← [Return] 
    ├─ [0] VM::addr(<pk>) [staticcall]
    │   └─ ← [Return] 0x29b7D9C8f9c4e158AeDC2bfC31D1931A519682Ed
    ├─ [30539] 0x5FbDB2315678afecb367f032d93F642f64180aa3::execute(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000055023074ca113074ca113074ca113074ca113074ca11000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, Signature({ signer: 0x29b7D9C8f9c4e158AeDC2bfC31D1931A519682Ed, yParity: 1, r: 0xa7d19736b0c8d7c143bc5ebb9f676c5207043ea918f78fcc339e5496ed3c285a, s: 0x0f86e650a01a9a6555917fc44ec3a87a3f53dc471fb63ec6dc94efc1d6b3b78e }))
    │   ├─ [0] 0x3074Ca113074ca113074CA113074CA113074CA11::fallback{value: 10000000000000000}()
    │   │   └─ ← [Stop] 
    │   └─ ← [Stop] 
    ├─ [0] VM::stopBroadcast()
    │   └─ ← [Return] 
    └─ ← [Stop] 


Script ran successfully.

## Setting up 1 EVM.
==========================
Simulated On-chain Traces:

  [35039] 0x5FbDB2315678afecb367f032d93F642f64180aa3::execute(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000055023074ca113074ca113074ca113074ca113074ca11000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, Signature({ signer: 0x29b7D9C8f9c4e158AeDC2bfC31D1931A519682Ed, yParity: 1, r: 0xa7d19736b0c8d7c143bc5ebb9f676c5207043ea918f78fcc339e5496ed3c285a, s: 0x0f86e650a01a9a6555917fc44ec3a87a3f53dc471fb63ec6dc94efc1d6b3b78e }))
    ├─ [0] 0x3074Ca113074ca113074CA113074CA113074CA11::fallback{value: 10000000000000000}()
    │   └─ ← [Stop] 
    └─ ← [Stop] 


==========================

Chain 41144114

Estimated gas price: 0.081543882 gwei

Estimated total gas used for script: 86314

Estimated amount required: 0.000007038378630948 ETH

==========================
##
Sending transactions [0 - 0].
##
Waiting for receipts.

Transactions saved to: /app/foundry/broadcast/Execute.s.sol/41144114/sendEth-latest.json

Sensitive values saved to: /app/foundry/cache/Execute.s.sol/41144114/sendEth-latest.json

Error: 
Transaction Failure: 0x9d7edbd23db203be0a7dda87f7785f7848da051eaf4fe4a52517ac6374c1a3d9
make: *** [foundry] Error 1

EIP-5806: Delegate Transaction

There's a recent PR in revm for EIP-5806: bluealloy/revm#1184

The EIP spec:
https://eips.ethereum.org/EIPS/eip-5806

EIP-5806 essentially allows EOAs to execute arbitrary code, one of the benefits is allowing for easier tx batching if used with a multicall contract.

This introduces a new transaction type, which would be difficult for us to fully support with the current reth API, so this one seems lower priority.

RIP-7560: Native Account Abstraction

RIP-7560 is described as a combination of EIP-2938 and ERC-4337, meant to be backwards compatible with ERC-4337.

The spec: ethereum/RIPs#3

This overview is split up into sections outlining either:

  • What would need to be implemented (if the reth node builder supports it)
  • What additional extensibility would the node builder require

The proposal is complex and would require many changes, some of which are currently not possible with the reth node builder.

AA transaction type

A new EIP-2718 transaction type is introduced. This would be difficult to support with the current node builder API.

The new transaction type is encoded like this:

0x04 || 0x00 || rlp([
  chainId, sender, nonce, builderFee,
  callData, paymasterData, deployerData,
  maxPriorityFeePerGas, maxFeePerGas,
  validationGasLimit, paymasterGasLimit, callGasLimit,
  accessList, signature
])

This also adds a "transaction counter header" which adds more encoding / decoding complexity. Discussion here on whether or not this should be included in the block:
ethereum/RIPs#3 (comment)

NonceManager pre-deployed contract

Transaction nonces for AA_TYPE transactions are now not necessarily sequential, see the "Non-sequential nonce support" section.

Nonce management and validation are proposed as a pre-deployed contract. There is no bytecode yet.

Transaction validation "Frames"

AA transactions are validated and executed in a specific order, similar to ERC-4337:

  1. Validation
    • nonce validation and increment frame (required, uses predeployed contract)
    • sender deployment frame (once per account)
    • sender validation frame (required)
    • paymaster validation frame (optional)
  2. Execution phase
    • sender execution frame (required)
    • paymaster post-transaction frame (optional)

These steps could be implemented with the validation and execution handlers in the EVM builder.
Mempool DoS prevention rules are shared between ERC-4337 and RIP-7560, located here:
https://eips.ethereum.org/EIPS/eip-7562

EIP-7562 would need its own issue and scope

  • EIP-7562: Account Abstraction Validation Scope Rules

Opcode values

This is included as a reference:

Opcode Name Solidity Equivalent Value
CALLER msg.sender The AA_ENTRY_POINT address. AA_SENDER_CREATOR for the "deployment frame".
ORIGIN tx.origin The transaction sender address
CALLDATA* msg.data The transaction data is set to inputs of the corresponding frame

Unused gas penalty charge

There is a penalty for unused gas, discussion on why this is included here:
ethereum/RIPs#3 (comment)

Alt mempool

The new transaction type is suggested to be propagated in a 4337 style alt mempool:

Such transactions MUST NOT be propagated through the default transaction mempool as they will be rejected by the nodes and the sending node will be blocked as a spammer. They may be propagated in the alternative mempool that allows them explicitly as defined in ERC-7562.

Block validation

Block validation is extended with calls to the AA predeployed contract. This logic would be possible to implement if the reth processor / executor were configurable.

RPC changes

This requires changes to:

  • eth_call
  • eth_getTransactionReceipt
  • eth_sendTransaction
  • eth_sendRawTransaction

Open questions and notes

  • Is an alt mempool optional, or required?
  • The spec seems incomplete, has no reference implementation, and there are many quirks with long github discussions without a clear resolution.
  • It's not clear which EIPs are required. Is EIP-2938 required?

This is very complex and requires more time to understand fully - this issue is here for now, and the fact that this RIP is so complex motivates some things to add to the node builder. It's also possible that the spec could be made simpler, and some of the quirks could be removed with more thought.

Introduce basic cli command and help menu

Right now the alphanet binary just runs the node, with no help options, options for overriding the discovery port, etc:

dan@Dans-MacBook-Pro-4 ~/p/alphanet (main) [101]> ./target/debug/alphanet --help
2024-03-21T19:55:55.396789Z  INFO Configuration loaded path="/var/folders/65/m26_cf0d1lbdnp4dvzztr0th0000gn/T/reth-test-MouAvtXj/reth.toml"
2024-03-21T19:55:55.397075Z  INFO Database opened
2024-03-21T19:55:55.413599Z  INFO Pre-merge hard forks (block based):
- Frontier                         @0
- Homestead                        @0
- Tangerine                        @0
- SpuriousDragon                   @0
- Byzantium                        @0
- Constantinople                   @0
- Petersburg                       @0
- Istanbul                         @0
- Berlin                           @0
- London                           @0
Merge hard forks:
- Paris                            @0 (network is not known to be merged)

Post-merge hard forks (timestamp based):
- Shanghai                         @0
- Cancun                           @0

2024-03-21T19:55:55.470785Z  INFO Transaction pool initialized
2024-03-21T19:55:55.470874Z  INFO Connecting to P2P network
2024-03-21T19:55:55.474633Z  INFO StaticFileProducer initialized
2024-03-21T19:55:55.475025Z  INFO Pruner initialized prune_config=PruneConfig { block_interval: 5, segments: PruneModes { sender_recovery: None, transaction_lookup: None, receipts: None, account_history: None, storage_history: None, receipts_log_filter: ReceiptsLogPruneConfig({}) } }
2024-03-21T19:55:55.475238Z  INFO Consensus engine initialized
2024-03-21T19:55:55.475336Z  INFO Engine API handler initialized

We should add most of the reth CLI commands, as well as the help menu.

  • CLI commands
  • Help menu

We should do something similar to how op-reth is built and launched:
https://github.com/paradigmxyz/reth/blob/6eb7397aa2c49c90922691cb0e176d973bbb441a/bin/reth/src/optimism.rs#L26

General project questions

I've been researching Reth AlphaNet a bit. Thanks for the effort so far!

  1. My impression is that it is basically Reth with optimism flag enabled and three EIPs supported. Is that correct?
  2. What about the sequencer? Is the alphanet command somehow planned to also spawn one? In this documentation paragraph it's marked with TODO:
    alphanet node
     --chain etc/alphanet-genesis.json \
     --rollup.sequencer-http <TODO> \
     ...
    
  3. I'm curious if it can in any way be of use to non-EVM experimenting; or am I completely missing the point?

Sorry if this is not the right place to ask, I thought I'd get the quickest answer here.

Rely on revm implementation of EIP-2537

Now that we have an implementation of EIP-2537 in revm, we should import that code now instead. There were also many bug fixes for EIP-2537 included in revm which should apply here as well.

`AUTH`, `AUTHCALL` integration in EVM config

EIP-3074 is another account abstraction-related EIP that would be interesting to have on AlphaNet.

This involves adding two new instructions, in the existing custom evm config.

This will require at least adding an entry to an instruction table, and using that instruction table in a custom revm Handler:
https://github.com/bluealloy/revm/blob/0d42796362c9f90d44f902e99417f570c16b4901/crates/interpreter/src/instructions/opcode.rs#L31

The spec:
https://eips.ethereum.org/EIPS/eip-3074

There are already solc and foundry implementations, although not using the evm builder:
https://github.com/clabby/eip-3074-foundry
also:
https://github.com/anna-carroll/3074

bug: `AUTH` opcode should unset and push0 if authority account has code

From EIP 3074:

authority is the address of the account which generated the signature. If EXTCODESIZE of authority is not zero, consider the operation unsuccessful and unset authorized.

What I understand from this:

  • After loading the account, check the code size
    • If not 0, unset authorized, push 0, stop executing the logic of AUTH and continue the execution of the current frame.

Which means that here we should add something like (pseudocode)

if acc.code.len() != 0 {
   push_stack(0);
   ctx.remove(AUTHORIZED_VAR_NAME);
   return;
}

let authority_account = match evm.context.evm.load_account(authority) {
Ok(acc) => acc,
Err(_) => {
interp.instruction_result = InstructionResult::Stop;
return;
}
};

I'd be glad to PR this if approved :)

EIP-2537: Precompile for BLS12-381 curve operations

We should add EIP-2537, spec here:
https://eips.ethereum.org/EIPS/eip-2537

The precompile has ABIs for the following operations:

  • G1 addition
  • G1 multiplication
  • G1 multiexponentiation
  • G2 addition
  • G2 multiplication
  • G2 multiexponentiation
  • Pairing
  • Mapping Fp element to G1 point
  • Mapping Fp element to G2 point

There are also some test vectors, although this will need to be tested more than with just these:
https://eips.ethereum.org/assets/eip-2537/bench_vectors

We use blst in c-kzg-4844, and it has rust bindings, so that could be used here as well:
https://github.com/supranational/blst

Tasks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.