GithubHelp home page GithubHelp logo

microsoft / eevm Goto Github PK

View Code? Open in Web Editor NEW
355.0 23.0 81.0 3.59 MB

Enclave ready EVM (eEVM) is an open-source, standalone, embeddable, C++ implementation of the Ethereum Virtual Machine.

Home Page: http://microsoft.com/blockchain

License: MIT License

CMake 2.44% C++ 97.52% Shell 0.04%
blockchain ethereum solidity enclave sgx

eevm's Introduction

Enclave EVM

Enclave EVM (eEVM) is an open-source, standalone, embeddable, C++ implementation of the Ethereum Virtual Machine. It was originally built to run within a TEE (ie, SGX enclave) on top of the Open Enclave SDK, for use with Microsoft's Confidential Consortium Framework.

eEVM GitHub Actions CI

Description

The main entry point is eevm::Processor::run(). You will need to provide eevm::Processor with an implementation of eevm::GlobalState to handle all interactions with permanent state. The source includes eevm::SimpleGlobalState as an example backed by std::map, but other instances will likely want an implementation which provides permanent storage - perhaps a wrapper to read/write data from the Ethereum blockchain.

eEVM supports all opcodes from Ethereum's Homestead release, as listed in opcode.h. Note that this does not include more recent opcodes such as RETURNDATACOPY or RETURNDATASIZE from EIP #211.

The implementation ignores all gas costs - gas is not spent, tracked, or updated during execution, and execution will never throw an outofgas exception. However, it may still be necessary to pass a sensible initial gas value to eevm::Processor::run() in case the bytecode calculates or verifies gas budgets itself. It also does not provide the precompiled contracts at addresses 1 to 8.

So far, the code is not particularly optimized in any dimension. In fact, it is in experimental state.

Dependencies

  • CMake. Minimum version 3.10.

Build and Test

We build and test eEVM on Linux and Windows on x86-64, but it should be functional cross-platform.

Linux

Build the static library and tests.

mkdir build
cd build
cmake ..
make

It is also possible to build with Ninja or another generator of choice, and the code will compile with either GCC or Clang (other compilers are untested).

Run the tests.

cd build
ctest -VV

Windows / Visual Studio 2017

Open the Visual Studio 2017 developer command prompt. Create .sln and .vcxproj files and build the static library and tests as follows.

mkdir build
cd build
cmake ..
msbuild ALL_BUILD.vcxproj

Run the tests.

cd build
ctest -C debug

More on tests

To run the tests outside of CTest you will need to provide the path to the test cases as an environment variable.

cd build
export TEST_DIR=../3rdparty/test_cases/
./eevm_tests

The full test suite contains some longer performance tests which are skipped by default. For full coverage, these can be run by passing the no-skip option to the test app - these should complete in minutes, while the default tests should complete in under a second.

cd build

time TEST_DIR=../3rdparty/test_cases/ ./eevm_tests
...
real    0m0.424s

time TEST_DIR=../3rdparty/test_cases/ ./eevm_tests -ns
...
real    2m11.306s

Note that the test harness skips several test cases. Some of these test features which are not supported (gas exhaustion, huge address space), while others appear malformed (do not match the documented test format).

Third-party components

We rely on several open source third-party components, attributed under THIRD_PARTY_NOTICES.

Keccak

The Keccak sources were created from the reference KeccakCodePackage by running make FIPS202-opt64.pack. Unfortunately, we cannot use the probably more optimized ASM versions for now, because they are neither PIC nor Visual Studio compatible.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repositories using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

eevm's People

Contributors

achamayou avatar azure-pipelines[bot] avatar eddyashton avatar flxflx avatar jumaffre avatar marleyg avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar msftgits avatar unboxedtype 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eevm's Issues

Failing CI

We need a CI agent with a C++17 friendly compiler, and recent Boost. We were using Azure Pipelines' Hosted Ubuntu 16.04 agent and manually installing Boost, but the GCC 5.4 installed on those agents can't handle recent changes (std::apply, variadic packs).

I looked at using the VS2019 Hosted agent, but haven't found a suitably quick way of getting the Boost sources (wget equivalents are significantly slower, untar options are unfathomably slower). Next step is to look at using a custom Docker image with our dependencies pre-installed.

TEE implementation of eEVM

Is there an implementation of eEVM running in an enclave using the openenclave sdk publicly available? I'm trying to get it running, and have a few issues/questions:

  • Making all the standard libraries/boost available: I'm interested to see how this was accomplished in order to minimize the enclave's TCB
  • I'd love to see the edl, to get a better understanding of what functions are where etc.

Maybe my understanding of both this project and openenclave/there relationship are incorrect.

issues that runs eEVM inside the Openenclave TEE

Hi, I have already read all history issues before posting this one.

I am trying to run eEVM inside an Openenclave. Here is my case:

  • Ubuntu 18.04 x64, Intel SGX enabled.
  • I installed both of them (eEVM and Openenclave) and ran their samples successfully and seperately. But when I combine their samples to a single project, many compatibility problems occur.
  • One issue is eEVM is in C++ 17, while Openenclave is in C language. As far as I know, it's not able to call c++ by using C language directly. I have tried extern "C"{}, but still can't fix this compatibility problem.

Is there any sample code that running eEVM inside an Openenclave TEE? Or any idea to solve the above problem? Thank you.

build failed on Windows 10 with visual studio 2017

got following error message. Is there any other MACRO or third party libraries are needed?
fatal error C1083: Cannot open include file: 'nlohmann/json.hpp': No such file or dir
ectory [D:\eEVM\eEVM\evm.vcxproj]

My build environment:
Windows 10
Visual Studio 2017 Community
Boost 1.67.0

Add recent op codes

Since the eEVM was first implemented, additional op codes have been added to the EVM spec (notably RETURNDATASIZE, RETURNDATACOPY, and REVERT). Currently contracts must be compiled explicitly targeting the Homestead spec, or they will produce unaccepted op codes. Adding support for these would make it possible to run more recent real-world example contracts, and to validate the eEVM against current external test sets.

Add distinct Address type

Currently the 20-byte Addresses are simply a typedef for uint256_t. This means we can easily reuse the parsing and serialisation code, but introduces type confusion and memory bloat (32 bytes for every 20-byte Address). In particular, we always want to export an Address as a fixed-size 20 byte hex value, ideally checksum-encoded, whereas uint256_ts are written with variable length (rather than padded with leading 0s). We can achieve this by explicitly calling the correct functions everywhere we do these conversions, but it would be neater if these were automatically handled by the type system.

some bugs existed in my Ubuntu 16.04 Linux operating system

[  2%] Building CXX object CMakeFiles/eevm.dir/src/util.cpp.o
In file included from /home/ressull/eEVM/src/util.cpp:6:0:
/home/ressull/eEVM/include/eEVM/rlp.h: In function ‘auto eevm::rlp::encode_multiple(const std::tuple<_Elements ...>&)’:
/home/ressull/eEVM/include/eEVM/rlp.h:225:14: **error**: ‘apply’ is not a member of ‘std’
       return std::apply(
              ^
/home/ressull/eEVM/include/eEVM/rlp.h: In function ‘eevm::rlp::ByteString eevm::rlp::encode(Ts&& ...)’:
/home/ressull/eEVM/include/eEVM/rlp.h:235:10: **error**: expected ‘(’ before ‘constexpr’
       if constexpr (sizeof...(Ts) == 1 && !is_tuple<std::decay_t<Ts>...>::value)
          ^
/home/ressull/eEVM/include/eEVM/rlp.h:243:33: **error**: ‘apply’ is not a member of ‘std’
       const auto total_length = std::apply(
                                 ^
/home/ressull/eEVM/include/eEVM/rlp.h: In lambda function:
/home/ressull/eEVM/include/eEVM/rlp.h:244:52: **error**: expected primary-expression before ‘...’ token
         [](auto&&... term) { return (term.size() + ... + 0); }, nested_terms);
                                                    ^
/home/ressull/eEVM/include/eEVM/rlp.h:244:52: **error**: expected ‘)’ before ‘...’ token
/home/ressull/eEVM/include/eEVM/rlp.h:244:59: error: parameter packs not expanded with ‘...’:
         [](auto&&... term) { return (term.size() + ... + 0); }, nested_terms);
                                                           ^
/home/ressull/eEVM/include/eEVM/rlp.h:244:59: note:         ‘term’
/home/ressull/eEVM/include/eEVM/rlp.h: In function ‘eevm::rlp::ByteString eevm::rlp::encode(Ts&& ...)’:
/home/ressull/eEVM/include/eEVM/rlp.h:249:7: **error**: ‘apply’ is not a member of ‘std’
       std::apply(
       ^
/home/ressull/eEVM/include/eEVM/rlp.h: In lambda function:
/home/ressull/eEVM/include/eEVM/rlp.h:251:74: **error**: expected primary-expression before ‘...’ token
           ((flattened.insert(flattened.end(), term.begin(), term.end()), ...));
                                                                          ^
/home/ressull/eEVM/include/eEVM/rlp.h:251:74: **error**: expected ‘)’ before ‘...’ token
/home/ressull/eEVM/include/eEVM/rlp.h:251:79: **error**: expected ‘)’ before ‘;’ token
           ((flattened.insert(flattened.end(), term.begin(), term.end()), ...));
                                                                               ^
/home/ressull/eEVM/include/eEVM/rlp.h:251:79: **error**: parameter packs not expanded with ‘...’:
/home/ressull/eEVM/include/eEVM/rlp.h:251:79: note:         ‘term’
/home/ressull/eEVM/include/eEVM/rlp.h: At global scope:
/home/ressull/eEVM/include/eEVM/rlp.h:320:24: **error**: ‘is_integral_v’ is not a member of ‘std’
       std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                        ^
/home/ressull/eEVM/include/eEVM/rlp.h:320:24: **error**: ‘is_integral_v’ is not a member of ‘std’
/home/ressull/eEVM/include/eEVM/rlp.h:320:44: **error**: template argument 1 is invalid
       std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                                            ^
/home/ressull/eEVM/include/eEVM/rlp.h:320:54: **error**: invalid use of ‘::’
       std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                                                      ^
/home/ressull/eEVM/include/eEVM/rlp.h:320:54: **error**: expected ‘;’ at end of member declaration
/home/ressull/eEVM/include/eEVM/rlp.h:320:67: **error**: expected unqualified-id before ‘<’ token
       std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                                                                   ^
/home/ressull/eEVM/src/util.cpp:59:1: **error**: expected ‘}’ at end of input
 } // namespace eevm
 ^
/home/ressull/eEVM/src/util.cpp:59:1: error: expected unqualified-id at end of input
/home/ressull/eEVM/src/util.cpp:59:1: error: expected ‘}’ at end of input
/home/ressull/eEVM/src/util.cpp:59:1: error: expected ‘}’ at end of input
CMakeFiles/eevm.dir/build.make:114: recipe for target 'CMakeFiles/eevm.dir/src/util.cpp.o' failed
make[2]: *** [CMakeFiles/eevm.dir/src/util.cpp.o] Error 1
CMakeFiles/Makefile2:105: recipe for target 'CMakeFiles/eevm.dir/all' failed
make[1]: *** [CMakeFiles/eevm.dir/all] Error 2
Makefile:94: recipe for target 'all' failed
make: *** [all] Error 2

I am not quite familiar with the C++ code, but seems like these errors are related to the gcc version, right? My gcc version is 5.4.0 20160609

ERROR: test case THREW exception: Must set path to test cases in TEST_DIR environment variable

ressull@ressull-Inspiron-3670:~/eEVM/build$ sudo ./eevm_tests 
[doctest] doctest version is "2.0.0"
[doctest] run with "--help" for options
===============================================================================
/home/ressull/eEVM/tests/harness.cpp:164:
TEST SUITE: logic
TEST CASE:  vmBitwiseLogicOperationTest

/home/ressull/eEVM/tests/harness.cpp:164: ERROR: test case THREW exception: Must set path to test cases in TEST_DIR environment variable

===============================================================================
/home/ressull/eEVM/tests/harness.cpp:169:
TEST SUITE: logic
TEST CASE:  vmEnvironmentalInfoTest

/home/ressull/eEVM/tests/harness.cpp:169: ERROR: test case THREW exception: Must set path to test cases in TEST_DIR environment variable

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

I got a question, when I running the ./eevm_tests. it shows ERROR: test case THREW exception: Must set path to test cases in TEST_DIR environment variable.
Actually, I ran "export" also set the export in the /etc/profile

The hello_world/sum all works well, only the eevm_tests. But the thing is I already set the env.

Thanks.

RLP decoding doesn't throw an error on improper cases

Here are some RLP strings that are decoded normally although the result is incorrect

  1. (empty byte 00)
f86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c4400b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3
0xf86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8cef804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3

Can be verified online at https://codechain-io.github.io/rlp-debugger/ (try removing 00 from #1)

`to_big_endian` does not work well in SGX environment

I tried to run eEVM in SGX, but every time I call to_big_endian in the byte to byte mode, no matter how long the input array is, the output will only have 8 valid bytes, the rest remains 0. I also checked the source code and find out that the >> only moves the first 8 bytes. By the way, the host operating system that I am running is Ubuntu 18.04 64 bits.

to_json/from_json format suggestion

Hi!

I have a suggestion regarding evm::to_json, evm::from_json JSON formatting.
At the moment, to deserialize an Account object from JSON file, you have to provide it in the following format:

{
            "address" : "0x100",
            "balance" : "0x100000000000000",
            "nonce"   : 0,
            "code"    : [0]
}

All is fine for address and balance, for the nonce I have to provide an integer instead of integer string, and for the code I have to provide array of values.
The last thing looks very inconvenient because most of the tools (solc, web3 console at least?) output code part of an address in a hex string, so we have a compatibility issue here.

What do you think about making the code field a hex-string compatible? I mean, is there any special arguments against it? The same goes for nonce, actually.

If you don't mind, I would make it on my own producing pull request afterwards.

Thanks!

Add precompiled contracts

To support execution of more real-world contracts, the eEVM should support the precompiled contracts specified in the Yellow Paper.

How to run the eevm after compilation

Is there any sample code that shows how to pass a bytecode to the evm and run it. I noticed that it is possible through the test case samples. I will be glad to see how to execute the code without the test harness.

Thank you

Example of decoding signed TX

Having some difficulties decoding a signed TX using eEVM, for example:

f866808609184e72a0008303000094b0920c523d582040f2bcb1bd7fb1c7c1ecebdb34808025a0e948a3307231941c23f678a0194089fcd52bd62310ee29b7a589e8c60bfec02aa064154144171470510d686559fe3e168f38a4e02c61e7b1aa2f8a19889836534c

Are there any examples of this @eddyashton ?

Replace Boost dependency

Boost is a large, complicated dependency for this otherwise simple project. The only thing we use it for is wide integers, specifically fixed-width 256-bit unsigned integers. Even here there are rapid version incompatibilities, and we may need to specify a specific Boost version.

We should be able to use a smaller implementation wide int implementation (without dynamic sizing support, without obfuscating templates), and if needed we can write our own.

Add optional gas tracking

While not required for the eEVM's original purpose, other users of the eEVM will want gas to be tracked and expended as specified in the white paper.

If added, this should be an optional additional feature - disabled at compile time in applications where it is not needed.

This is currently a low priority, but I expect it will eventually be a blocking requirement for a potential user.

Linux build instructions...

On Ubuntu 18.04 the instuctions:

mkdir build; cd build
cmake -GNinja ..
ninja

...builds the file build.ninja in the root, not the build folder, & nor is it called `ninja.

Improve general test coverage

We use 3rd party test cases through harness.cpp, but many are disabled. Some for good reasons - gas tracking, oversized exponents - but others fail for unknown reasons.

We should investigate these remaining failures, and also see if there's anything to gain from pulling in more recent test cases. If we find significant untested holes, we should add our own test scenarios to cover these validated against another implementation.

Namespace and file cleanup

I think the evm namespace should be renamed to eevm for clarity in external projects. Additionally the external headers should be under include/eEVM/account.h. Then consumers can #include "eEVM/account.h", rather than the conflict-heavy #include "account.h".

These are annoying breaking changes for anyone currently using the library, but they're useful QoL improvements before we cut any official releases.

Do you have an EVM-C integration?

Do you have an implementation of an EVM-C wrapping of eEVM somewhere which could be published, so we can try using eEVM within Geth or similar on the Ethereum mainnet or testnets? Thanks!

Add abstract Account

Most of the eEVM's execution goes to virtual methods, allowing clients to implement global state + storage access logic, and handle each request however they wish. One place we don't have this is in Account - we currently hold a specific struct, and access its fields directly in the Processor.

Instead, Account should become a Storage like interface. The current implementation can become SimpleAccount, but other clients with different requirements can provide and store the account state any way they want at the call point.

Guides

Hello All

do you provide any docs on integrating eEVM into existing systems like UTXO or Cryptonote or similar ledgers?

thanks and br

timo

Can't compile with glibc master: SIGSTKSZ is no longer a constant

Couldn't build because this error popped up:
error: size of array 'altStackMem' is not an integral constant-expression
4189 | static char altStackMem[4 * SIGSTKSZ];

Easily fixed by using the latest version of doctest.h. I can't create a pull request though, so maybe someone with access can update?

Cannot build on Linux following README.md

I have got the following error.
`$ cmake -GNinja ..
CMake Error at CMakeLists.txt:3 (project):
Running

'/usr/sbin/ninja' '--version'

failed with:

die: error: must run as root
`
cmake version 3.11.2
ninja version 0.1.3 initializing

But the following commands works for me:
`mkdir build

cd build

cmake ..

make
`

how to use the enclave EVM in the SGX enclave to execute smart contract

I try to use the enclave EVM in the enclave of SGX. When I include the EVM file in the enclave, it will report some mistakes, because the EVM file include other files which can not be found in the enclave. I am confused. Due to the limitation of enclave, how can I use the enclave EVM in the enclave.

make error

when I ran

mkdir build
cd build
cmake ..
make

it shows

[  2%] Building CXX object CMakeFiles/eevm.dir/src/disassembler.cpp.o
[  4%] Building CXX object CMakeFiles/eevm.dir/src/processor.cpp.o
[  6%] Building CXX object CMakeFiles/eevm.dir/src/stack.cpp.o
[  9%] Building CXX object CMakeFiles/eevm.dir/src/transaction.cpp.o
[ 11%] Building CXX object CMakeFiles/eevm.dir/src/util.cpp.o
In file included from /opt/eEVM/src/util.cpp:6:0:
/opt/eEVM/include/eEVM/rlp.h: In function ‘auto eevm::rlp::encode_details::encode_multiple(const std::tuple<_Elements ...>&)’:
/opt/eEVM/include/eEVM/rlp.h:230:16: error: ‘apply’ is not a member of ‘std’
         return std::apply(
                ^~~
/opt/eEVM/include/eEVM/rlp.h: In function ‘eevm::rlp::ByteString eevm::rlp::encode(Ts&& ...)’:
/opt/eEVM/include/eEVM/rlp.h:242:10: error: expected ‘(’ before ‘constexpr’
       if constexpr (sizeof...(Ts) == 1 && !is_tuple<std::decay_t<Ts>...>::value)
          ^~~~~~~~~
/opt/eEVM/include/eEVM/rlp.h:251:33: error: ‘apply’ is not a member of ‘std’
       const auto total_length = std::apply(
                                 ^~~
/opt/eEVM/include/eEVM/rlp.h:257:7: error: ‘apply’ is not a member of ‘std’
       std::apply(
       ^~~
/opt/eEVM/include/eEVM/rlp.h: At global scope:
/opt/eEVM/include/eEVM/rlp.h:330:26: error: ‘is_integral_v’ is not a member of ‘std’
         std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                          ^~~
/opt/eEVM/include/eEVM/rlp.h:330:46: error: template argument 1 is invalid
         std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                                              ^
/opt/eEVM/include/eEVM/rlp.h:330:56: error: invalid use of ‘::’
         std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                                                        ^~~~~~~~~~~~~
/opt/eEVM/include/eEVM/rlp.h:330:56: error: expected ‘;’ at end of member declaration
/opt/eEVM/include/eEVM/rlp.h:330:69: error: expected unqualified-id before ‘<’ token
         std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, T>
                                                                     ^
/opt/eEVM/src/util.cpp:59:1: error: expected ‘}’ at end of input
 } // namespace eevm
 ^
/opt/eEVM/src/util.cpp:59:1: error: expected ‘;’ at end of input
/opt/eEVM/src/util.cpp:59:1: error: expected ‘}’ at end of input
/opt/eEVM/src/util.cpp:59:1: error: expected ‘}’ at end of input
/opt/eEVM/src/util.cpp:59:1: error: expected ‘}’ at end of input
CMakeFiles/eevm.dir/build.make:117: recipe for target 'CMakeFiles/eevm.dir/src/util.cpp.o' failed
make[2]: *** [CMakeFiles/eevm.dir/src/util.cpp.o] Error 1
CMakeFiles/Makefile2:108: recipe for target 'CMakeFiles/eevm.dir/all' failed
make[1]: *** [CMakeFiles/eevm.dir/all] Error 2
Makefile:97: recipe for target 'all' failed
make: *** [all] Error 2

image

my cmake version is 3.16.6

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.