Giter Site home page Giter Site logo

iotaledger / goshimmer Goto Github PK

View Code? Open in Web Editor NEW
389.0 48.0 114.0 671.88 MB

Prototype implementation of IOTA 2.0

Home Page: https://wiki.iota.org/goshimmer/welcome

License: Apache License 2.0

Go 86.52% Dockerfile 0.14% JavaScript 0.28% CSS 0.14% HTML 0.04% Makefile 0.03% TypeScript 11.84% Shell 0.40% Jinja 0.61%
iota tangle coordicide-modules golang cryptocurrency

goshimmer's Introduction


Prototype node software for an IOTA network without the Coordinator

Developer documentation portal

Discord StackExchange Apache 2.0 license Go version Latest release

AboutDesignGetting startedClient-Library and HTTP API referenceSupporting the projectJoining the discussion


About

This repository, called GoShimmer, is where the IOTA Foundation's Research Department tests the IOTA 2.0 modules to study and evaluate their performance.

GoShimmer is first and foremost a research prototype. As such, breaking changes can often happen. We invite researchers and developers to make use of this project as you see fit. Running experiments, test out new ideas, build PoC are all very welcome initiatives.

For a documentation, including tutorials and resources, we refer to the Documentation (Github link).

Design

The code in GoShimmer is modular, where each module represents either one of the IOTA 2.0 components, or a basic node function such as the gossip, ledger state, and API - just to mention a few.

Layers

GoShimmer's modularity is based on a combination of event-driven and layer-based approaches.

Client-Library and HTTP API reference

You can use the Go client-library to interact with GoShimmer (located under github.com/iotaledger/goshimmer/client).

You can find more info about this on our client-lib and Web API documentation.

Getting started

You can find tutorials on how to setup a GoShimmer node, writing a dApp, obtaining tokens from the faucet and more in the GoShimmer documentation.

Compiling from source

We always recommend running your node via Docker. However, you can also compile the source and run the node from the compiled binary. GoShimmer uses RocksDB as its underlying db engine. That requires a few dependencies before building the project:

  • librocksdb
  • libsnappy
  • libz
  • liblz4
  • libzstd

Please follow this guide: https://github.com/facebook/rocksdb/blob/master/INSTALL.md to build above libs.

When compiling GoShimmer, just run the build script:

./scripts/build.sh

If you also want to link the libraries statically (only on Linux) run this instead:

./scripts/build_goshimmer_rocksdb_builtin.sh

Finally, download the latest snapshot and make sure to place it in the root folder of GoShimmer:

wget -O snapshot.bin https://dbfiles-goshimmer.s3.eu-central-1.amazonaws.com/snapshots/nectar/snapshot-latest.bin

Supporting the project

If you want to contribute to the code, consider posting a bug report, feature request or a pull request.

When creating a pull request, we recommend that you do the following:

  1. Clone the repository
  2. Create a new branch for your fix or feature. For example, git checkout -b fix/my-fix or git checkout -b feat/my-feature.
  3. Run the go fmt command to make sure your code is well formatted
  4. Document any exported packages
  5. Target your pull request to be merged with dev

Joining the discussion

If you want to get involved in the community, need help getting started, have any issues related to the repository or just want to discuss blockchain, distributed ledgers, and IoT with other people, feel free to join our Discord.

goshimmer's People

Contributors

acha-bill avatar alexsporn avatar apenzk avatar bingyanglin avatar capossele avatar cyberphysic4l avatar daria305 avatar dependabot[bot] avatar dr-electron avatar evanfeenstra avatar galrogozinski avatar georgysavva avatar hmoog avatar jakescahill avatar jkrvivian avatar jonastheis avatar jorgemmsilva avatar karimodm avatar kilianhln avatar luca-moser avatar lucas-tortora avatar lzpap avatar muxxer avatar nuriel77 avatar phyloiota avatar piotrm50 avatar rajivshah3 avatar teeveeess avatar thethorne48 avatar wollac 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  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

goshimmer's Issues

Spammer API: TPS parameter not working

Currently, calling the spammer with a specific TPS parameter is not working: the spammer keeps sending 1000 TPS even if i call:

curl localhost:8080/spammer?cmd=start&tps=5

It looks that request.Tps is always read as equal to ZERO, even if a tps=20 parameters is sent through the GET request.
Probably, the convertion from STRING to INT of the TPS parameter in the GET request is missing (or not working?).

image

I did a test in order to see what happens if i attach a word instead of a number to the TPS parameter:
curl localhost:8080/spammer?cmd=start&tps=test

The node start spamming with 1000 TPS.

There is a problem about memory when i tried spamming with 10k tps.

  1. Memory still be same when i stopped spamming. So i think we need adjust options about memory for small devices, that it can automatically write data to a file when it reach a limit.

How do you suggest about value for the parameter below:
NumMemtables, MaxTableSize, NumCompactors

  1. The caching doesn't work good. I tried adding a log in the function GetApprovers and it is calling maybe 270k a read statement to a function getApproversFromDatabase after some minutes with spamming tps = 10k

Untitled

Documentation about TX fields received through ZMQ channel

The documentation reports 10 field of information about the TX content on this link (not considering the first field which just report "tx"): https://docs.iota.org/docs/node-software/0.1/goshimmer/how-to-guides/subscribe-to-events

image

By the way, on the GO code i found 12 fields (again not considering the first field which just report "tx"): https://github.com/iotaledger/goshimmer/blob/master/plugins/zeromq/plugin.go

image

And the current number of fields is even found in each single TX (screenshot from my ZMQ listener):

image

image

I suggest to update the documentation on https://docs.iota.org/docs/node-software/0.1/goshimmer/how-to-guides/subscribe-to-events

Update the readme for the v0.1.0 release

  • Describes the different branches on the repository and what the represent/investigate.
  • Link to the autopeering and FPC sim repository
  • Setting up a development environment
  • Install instructions and config example
  • Contribution guide and a section with avatars of users which have contributed

Shutdown doesn't work properly

Hi!

If I hit CTRL+C in the terminal, the node starts to shutdown, but somehow hangs. After some time I hit the CTRL+C again... and then it forces the shutdown 🤷‍♂️

grafik

Fix error handling when adding neighbor that does not support gossip

panic: peer does not support gossip

goroutine 401 [running]:
github.com/iotaledger/goshimmer/packages/gossip.GetAddress(0xc00006e200, 0x1575940, 0xc0004ee058)
        /root/goshimmer/packages/gossip/common.go:17 +0xa4
github.com/iotaledger/goshimmer/plugins/gossip.configureEvents.func4(0xc00006e200)
        /root/goshimmer/plugins/gossip/plugin.go:57 +0x4f
github.com/iotaledger/goshimmer/packages/gossip.peerCaller(0xba3740, 0xd15520, 0xc0004ae630, 0x1, 0x1)
        /root/goshimmer/packages/gossip/events.go:31 +0x62
github.com/iotaledger/hive.go/events.(*Event).Trigger(0xc000118a50, 0xc0004ae630, 0x1, 0x1)
        /root/go/pkg/mod/github.com/iotaledger/[email protected]/events/event.go:31 +0xdb
github.com/iotaledger/goshimmer/packages/gossip.(*Manager).addNeighbor(0xc00078c900, 0xc00006e200, 0xc000636ec0, 0x0, 0x0)
        /root/goshimmer/packages/gossip/manager.go:183 +0xd8
github.com/iotaledger/goshimmer/packages/gossip.(*Manager).AddInbound(0xc00078c900, 0xc00006e200, 0xd15260, 0x0)
        /root/goshimmer/packages/gossip/manager.go:102 +0x8e
github.com/iotaledger/goshimmer/plugins/gossip.configureEvents.func2.1(0xc0000f1fb0)
        /root/goshimmer/plugins/gossip/plugin.go:43 +0x50
created by github.com/iotaledger/goshimmer/plugins/gossip.configureEvents.func2
        /root/goshimmer/plugins/gossip/plugin.go:42 +0x3f
root@goshimmer:~/goshimmer# vim config.json

goshimmer on raspberry armv7l - cannot allocate memory

Hi there,

trying to run shimmer on Linux kali 4.19.55-Re4son-v7l+ #1 SMP Sun Jun 30 15:39:30 AEST 2019 armv7l GNU/Linux on a Raspberry Pi4 4GB 32 bit OS.

Go Version: go version go1.12.7 linux/arm

I get a "cannot allocate memory" error.

I tried to compile with this command:

env GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=1 go build -o shimmer

When starting it looks like this:

memory_error

Any ideas how to overcome the memory error?

Assure consistent application name

Currently the names shimmer and goshimmer are used in parallel. This should be consistent.
The name is used in the following locations:

  • README
  • Name displayed in the status screen
  • Binary name in Makefile
  • Name of the default log file configured in config.json
  • Binaries created with goreleaser

Adjust webapi endpoints

rename:

  • findTransactions to findTransactionHashes
  • getTransactions to getTransactionObjectsByHash
  • getTrytes to getTransactionTrytesByHash

leave:

  • broadcastData
  • spammer

panic: zmq4: could not exchange greetings

Log section:

...skipping...
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Starting Plugin: Spammer ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Starting background workers ...
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] WebAPI: Starting Web Server ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [ INFO ] Auto Peering: Starting UDP Server (port 14626) ...
Jul 26 16:29:09 node0 ubuntu[10661]: [ INFO ] Auto Peering: Starting TCP Server (port 14626) ...
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Gossip: Starting Send Queue Dispatcher ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [ INFO ] Auto Peering: Starting Chosen Neighbor Processor ...
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Auto Peering: Starting Chosen Neighbor Processor ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Bundle Processor: Starting Bundle Processor ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Tangle: Starting Solidifier ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Gossip: Starting TCP Server (port 14666) ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [ INFO ] Auto Peering: Starting Ping Processor ...
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Auto Peering: Starting Ping Processor ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Auto Peering: Starting UDP Server (port 14626) ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Bundle Processor: Starting Value Bundle Processor ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] ZeroMQ: Starting ZeroMQ Publisher (port 5556) ... done
Jul 26 16:29:09 node0 ubuntu[10661]: [  OK  ] Auto Peering: Starting TCP Server (port 14626) ... done
Jul 26 16:31:41 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / 5b839bea06dbb61ef9b4f7a43526e4245a17bbe0
Jul 26 16:31:41 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 10.233.96.0 / bf8cfc87e0f38a5793baf645d6e7be1a810fabed
Jul 26 16:31:41 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 10.233.96.0 / 52d77c9901d04c6bce76fe421e2a6fdc58fafddf
Jul 26 16:31:47 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / 73c26ca1810666ca6b70947dc9a9324b7198a4ec
Jul 26 16:31:47 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / 95030b3150264a0a248765c998ec86ea0df94a20
Jul 26 16:31:52 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / 824737ce28e5b00c6ad8c68279c92a914c8546e4
Jul 26 16:34:17 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / 4913107a290feb2eaaaa630951100eff33962a1b
Jul 26 16:34:17 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / ada88939f9f69fcec39725a59b1599643e5db9ad
Jul 26 16:34:17 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 10.233.96.0 / f2c380146010798b2a737713954c81561de3b781
Jul 26 16:36:54 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / 58fc322713f263bb26f420df97d239a1efde1fe7
Jul 26 16:37:10 node0 ubuntu[10661]: [ INFO ] Auto Peering: new peer discovered: 164.68.105.123 / 232c523ceb5bda6b7291f8b34736e1119c3f30b8
Jul 26 16:44:21 node0 ubuntu[10661]: [  OK  ] Gossip: new neighbor added [email protected]:14666
Jul 26 16:51:57 node0 ubuntu[10661]: panic: zmq4: could not exchange greetings: zmq4: could not recv greeting: read tcp 140.116.82.61:5556->67.205.184.67:32766: read: c
Jul 26 16:51:57 node0 ubuntu[10661]: goroutine 384 [running]:
Jul 26 16:51:57 node0 ubuntu[10661]: github.com/go-zeromq/zmq4.(*socket).accept(0xc001be4000)
Jul 26 16:51:57 node0 ubuntu[10661]:         /home/ubuntu/go/pkg/mod/github.com/go-zeromq/[email protected]/socket.go:178 +0x1b0
Jul 26 16:51:57 node0 ubuntu[10661]: created by github.com/go-zeromq/zmq4.(*socket).Listen
Jul 26 16:51:57 node0 ubuntu[10661]:         /home/ubuntu/go/pkg/mod/github.com/go-zeromq/[email protected]/socket.go:157 +0x17b
Jul 26 16:51:57 node0 systemd[1]: goshimmer.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
Jul 26 16:51:57 node0 systemd[1]: goshimmer.service: Failed with result 'exit-code'.

Add config keys to make bind addresses configurable

  • Use a single bindAddress key inside the configuration to configure the bind address for gossip and autopeering. The config key lives under the network object.
  • externalAddress, the external IP address under which the node is reachable under the autopeering config object. If it is set to auto, we use myip.com to automatically retrieve the IP address.
  • Also add a key for the webpi bind address under webapi config object, called bindAddress.
  • Make also the port adjustable for the webapi.

Make autopeering filter and ignore offline nodes.

Nodes that have been offline for a prolonged times should not be contacted by the autopeering forever and ever.

For this, we need to keep track of when a peer was seen the first and the last time and then adjust the filter functions to check these properties.

panic: runtime error: invalid memory address or nil pointer dereference

I got this error on the latest commit of master branch without spamming, running on Ubuntu 16.04.
This error occurs randomly, the first time took 54mins and the second time took around 18hours to this error.

Log Section:

[  OK  ] Gossip: new neighbor added [email protected]:14666
[  OK  ] Gossip: existing neighbor removed [email protected]:14666
[  OK  ] Gossip: new neighbor added [email protected]:14666
[  OK  ] Gossip: existing neighbor removed [email protected]:14666
[  OK  ] Gossip: new neighbor added [email protected]:14666
[  OK  ] Gossip: existing neighbor removed [email protected]:14666
[  OK  ] Gossip: new neighbor added [email protected]:14666
[  OK  ] Gossip: existing neighbor removed [email protected]:14666
[  OK  ] Gossip: new neighbor added [email protected]:14666
[  OK  ] Gossip: existing neighbor removed [email protected]:14666
[  OK  ] Gossip: existing neighbor updated [email protected]:14666
[  OK  ] Gossip: existing neighbor removed [email protected]:14666
[  OK  ] Gossip: new neighbor added [email protected]:14666
[  OK  ] Gossip: existing neighbor updated [email protected]:14666
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x835b86]

goroutine 241542 [running]:
github.com/iotaledger/goshimmer/packages/network.(*ManagedConnection).Close(0x0, 0xabd839, 0xc)
        /home/jkrvivian/IOTA/goshimmer/packages/network/managed_connection.go:71 +0x26
github.com/iotaledger/goshimmer/plugins/autopeering/protocol.processIncomingResponse(0xc0011556e0, 0xc000113ab0)
        /home/jkrvivian/IOTA/goshimmer/plugins/autopeering/protocol/incoming_response_processor.go:20 +0xb7
created by github.com/iotaledger/goshimmer/plugins/autopeering/protocol.createIncomingResponseProcessor.func1
        /home/jkrvivian/IOTA/goshimmer/plugins/autopeering/protocol/incoming_response_processor.go:13 +0x48
jkrvivian:goshimmer $ 

Add address option for all port bindings

For any listener (e.g. zeromq, dashboard, spammer etc), not only allow to configure the port on the command line, but also the address.

Perhaps, instead of calling it port, just take an entire argument called "bind" something like: -dashboard-bind-address which accepts the common syntax with go applications:
:8080 which means 0.0.0.0:8080, or user can bind to any IP: 10.20.30.10:8080 etc...

This way a user can choose to which interface to bind any of the services (for example when having multiple interfaces)
Or, should a user want to bind to localhost in order to reverse proxy to any of the services, then having this option allows to bind to 127.0.01.

If support for IPv6 can also be addressed it would be really nice as well.

Implement a database version flag

We want to panic if someone starts the node with an incompatible version of the database and instruct the user to delete it. With every breaking change, we adjust the database version flag.

Eliminate the webapi.AddEndpoint

Eliminate the webapi.AddEndpoint in favor of directly calling the HTTP methods on "Server" in every HTTP call implementing plugin.

Implement HTTP API endpoints

  • broadcastData:
    • input: address trytes and data trytes
    • output: the hash of the generated transaction hash
  • getTrytes:
    • input: transaction hashes array
    • output: raw trytes of the transactions
  • getTransactions:
    • intput: transaction hashes array
    • output: json objects of the transactions
  • findTransactions:
    • input: address trytes array
    • ouput: transaction hashes
  • getNeighbors:
    • input: no input :(
    • output: json object arrays of the connected neighbors, split into two arrays named chosen and accepted

Disable: getTransactionsToApprove

Add shutdown orders to background workers in plugins

Currently all background workers are shutdown at the same time in no particular fashion. In certain cases this can lead plugins to stall out or block shutdown. Additionally, we need to ensure that the database is closed as the last step of the node, to ensure that all outstanding data is written to disk.

Support comma as well as spaces for list delimiters

Request

"," supported as well as "" for list delimiters

Rationale

Currently lists are passed to goshimmer using spaces as delimiters, e,g:

-node-enabled-plugins "plugin1 plugin2 etc"

This requires to quote the string of arguments, and in some cases (docker-compose/systemd) it is required to use nested quoting.

If possible to support , (comma) as delimiter then quoting will not be necessary in most cases.

System requirements: add GO version

I had some issues during building process of the GO solution as i was using GO 1.6.

It came out that the compilation can only be done on GO 1.12.7 (by Luca Moser on Discord).

I suggest to add this detail on the README file.

Add option to manually provide key pair

Currently the private and public key is stored in the database but there is no way to persist keys during a database reset.
Add an config option to provide the public and private key of the local node.

Crashs when using the spammer

I don't know if this issue is already known, so I open an issue for it. Feel free to close when this is already known.

Environment:

  • ARM64 (ARMv8, Scaleway)
  • Ubuntu 18.04.2
  • 4.9.93-mainline-rev1
  • go version go1.12.7 linux/arm64

Steps to reproduce

  1. Build shimmer go build -o shimmer
  2. Start shimmer ./shimmer
  3. Run the spammer in a web-browser http://[YOUR_IP]:8080/spammer?cmd=start&tps=10000
  4. Let it run for some minutes. It will crash with:
                                                                /root/go/pkg/mod/github.com/dgraph-io/[email protected]+incompatible/txn.go:696 +0x80
                    github.com/iotaledger/goshimmer/packages/database.(*databaseImpl).Set(0x40019e4580, 0x4009eaee40, 0x51, 0x0, 0x4000024c00, 0x5dc, 0x5dc, 0x51, 0x403fe67500)
                        /root/go/src/github.com/iotaledger/goshimmer/packages/database/database.go:75 +0x80
                           github.com/iotaledger/goshimmer/plugins/tangle.storeTransactionInDatabase(0x4009e88780, 0x51, 0x400b469800)
                                                        /root/go/src/github.com/iotaledger/goshimmer/plugins/tangle/transaction.go:91 +0xdc
                                                           github.com/iotaledger/goshimmer/plugins/tangle.onEvictTransaction.func1(0x4009e88780)
                                                                        /root/go/src/github.com/iotaledger/goshimmer/plugins/tangle/transaction.go:64 +0x28
                                                                           created by github.com/iotaledger/goshimmer/plugins/tangle.onEvictTransaction
                                                                        /root/go/src/github.com/iotaledger/goshimmer/plugins/tangle/transaction.go:63 +0x74
                                                                           root@```

Test whether actual gossiping works between nodes

  • Make a program which sends out transactions using the new API and then check after a cooldown whether the transactions are actually query-able on the other non listed nodes.
  • Make the other nodes to check configurable via a simple config.json file
  • Make the interval in which the program issues a transaction configurable
  • Program code is going to be located in a tool folder and is called: relay-checker

Fix the PoW race condition

  • Find out what the race condition actually effects
  • Can be seen when running GoShimmer with the race detector

GoShimmer node crashed overnight

The node running on my VPS crashed overnight, apparently during an auto-peering action (after almost a full-day of correct operations).
I'm running a Go compiled version of the node (not a docker version).

Following the suggestion of Muxxer on Discord, i upload:

  1. Print-screen of the error i get from Journalctl:
    image

  2. The commit reference of the node version i'm running:
    commit 895dfc09ce3ff57ef2c53d78000f77a6ee67fcbc

image

Any other information or log file required?

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.