Giter Club home page Giter Club logo

consensus_bft's Introduction

consensus_bft

类似Tendermint的共识协议,取消commit阶段并使用leader归票降低网络通信复杂度

编译docker镜像

docker build -t citacloud/consensus_bft .   

使用方法

$ consensus -h       
consensus 6.6.0
Rivtower Technologies <[email protected]>
This doc string acts as a help message when the user runs '--help' as do all doc strings on fields

USAGE:
    consensus <SUBCOMMAND>

OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information

SUBCOMMANDS:
    help    Print this message or the help of the given subcommand(s)
    run     run this service

consensus-run

运行consensus服务。

$ consensus run -h
consensus-run 
run this service

USAGE:
    consensus run [OPTIONS]

OPTIONS:
    -c, --config <CONFIG_PATH>    Chain config path [default: config.toml]
    -h, --help                    Print help information
    -l, --log <LOG_FILE>          log config path [default: consensus-log4rs.yaml]

参数:

  1. 微服务配置文件。

    参见示例example/config.toml

    其中:

    • consensus_port 为该服务监听的端口号。
  2. 日志配置文件。

    参见示例consensus-log4rs.yaml

    其中:

    • level 为日志等级。可选项有:ErrorWarnInfoDebugTrace,默认为Info
    • appenders 为输出选项,类型为一个数组。可选项有:标准输出(stdout)和滚动的日志文件(journey-service),默认为同时输出到两个地方。
$ consensus run -c example/config.toml -l consensus-log4rs.yaml
2022-03-10T10:04:09.850581+08:00 INFO consensus - start consensus bft
2022-03-10T10:04:09.851129+08:00 INFO consensus - grpc port of this service: 50001

状态转换

Leader

start

  1. Leader send new proposal success
  2. Leader send new proposal fail
  3. Leader retry send new proposal success
  4. When leader receive the Prevote vote from follower,if it has send the proposal, and collect above 2/3 Prevote votes then change to PrecommitWait
  5. ProposeWait timeout and leader has collect above 2/3 Prevote votes, then
  • send Prevote vote with None hash
  • start new round
  1. When leader receive the Precommit vote, and it has collect above 2/3 Precommit votes. If current leader isn't the (next height, init round) leader then change to CommitWait temporary and soon change to Commit else change to Commit
  2. Leader send message timeout and hasn't collect above 2/3 votes, change to NewView
  3. In the case below, change to Proposal
  • CommitWait timeout and deal old height success
  • Commit timeout and check and commit block failed, then start new round
  1. Leader has collect 2f NewView votes, start new round
  2. When leader receive Prevote, in the case below change to Proposal
  • has collect 2f Prevote and self.round behind round, start new round
  • hash in the voteset which is above 2/3 n is zero, start new round
  • hasn't receive the Proposal yet which the hash is above 2/3 n, start new round
  1. When leader receive Precommit, in the case below change to Proposal
  • hash in the voteset which is above 2/3 n is zero, start new round
  • self.proposal not equal the hash in the voteset which is above 2/3 n, start new round
  • else if check and commit block failed, then start new round

Follower

follower

  1. Follower hasn't receive the Proposal
  2. Follower has receive the Proposal and add to proposals, hash_proposals , set proposal and send Prevote
  3. When receive the LeaderPrevote , check it, save to wal and send Precommit
  4. In the case below, change to CommitWait/Commit
  • When receive the LeaderPrevote and change to PrecommitWait success, and if has receive LeaderPrecommit with above 2/3 Precommit from leader, then enter the follow case
  • When follower receive the LeaderPrecommit with above 2/3 Precommit votes and save to wal, If current leader isn't the (next height, init round) leader then change to CommitWait temporary and soon change to Commit else change to Commit
  1. Follower receive Precommit whose hash is zero or check and commit block failed, start new round, change to Proposal
  2. Follower receive Prevote whose hash is zero, or hasn't receive the proposal , then start new round, change to Proposal
  3. In the case below, change to Proposal
  • CommitWait timeout and deal old height success
  • Commit timeout and check and commit block failed, then start new round
  1. Follower send message timeout and send NewView message, then change to NewView
  2. Follower has collect 2f NewView votes, start new round

启动及运行流程

start

  • 启动

    • 加载配置
    • 创建controller<->bft, network<->bft, timeout->bft的通道channel,并将通道channel句柄放入bft_channels
    • 初始化bft并开始select loop
    • 启动server,添加uri匹配规则,监听指定端口,并将匹配的uri转发至相应的通道channel
  • 运行

    • controller->bftreconfigurecheck_block请求,做出相应处理,并返回处理结果
      • reconfigure
        • 更新auth_manageis_consensus_node
        • 如果当前节点是(next height, init round)leader,则请求controller GetProposal,根据结果值设置proposal self_proposal proposals及相关值,并发送new proposal
      • check_block
        • 检查收到的LeaderVote中的vote是否正确
    • network->bft的消息会根据其VoteMsgtype进行相应处理,并根据发送消息至其他节点
      • Proposal
        • 只有follower会收到该消息,在校验(height, round, step)通过,请求controller CheckProposal,将其加入votes
        • 上一步检查通过后,设置proposal self_proposal proposals,发送自己的Prevote消息,变更状态,设置超时时间
      • Prevote
        • leader收到消息校验(height, round, step)及消息的发送节点的正确性后,将其加入votes
        • 上一步检查通过后,检查Prevote数量进行相应处理,详见状态转换
      • Precommit
        • leader收到消息校验(height, round, step)及消息的发送节点的正确性后,将其加入votes
        • 上一步检查通过后,检查Precommit数量进行相应处理,详见状态转换
      • LeaderPrevote
        • follower收到消息校验(height, round, step),消息的发送节点的正确性,及其票数是否超过2/3后,将其加入votes,并保存至wal
        • 上一步检查通过后,做进一步处理,详见状态转换
      • LeaderPrecommit
        • follower收到消息校验(height, round, step),消息的发送节点的正确性,及其票数是否超过2/3后,将其加入votes,并保存至wal
        • 上一步检查通过后,做进一步处理,详见状态转换
      • NewView
        • 收到消息校验(height, round, step),消息的发送节点的正确性后,将其加入votes
        • 上一步检查通过后,若当前节点收到2fNewView,发送NewView消息,开始新的round
    • timeout->bft根据超时的消息类型及是否是对应height roundleader做相应处理

consensus_bft's People

Contributors

jerry-yu avatar pencil-yao avatar rink1969 avatar jlerxky avatar naughtydogofschrodinger avatar jayanring avatar acechef avatar

Stargazers

 avatar HAOYUatHZ avatar

Watchers

James Cloos avatar  avatar  avatar  avatar

consensus_bft's Issues

check_proposal_proof BUG

controller日志:

2022-04-26T09:35:06.108133053+00:00 INFO controller::chain - proposal 94869 block_hash 0x2df395ab24f84755dce322d318e4f842fa2809afbfa3f101c4de8bf63da4315c prevhash 0x1e70788c0e257a5441d5b289a5290eb3f3aaa7fd7bf9b82142f973bf91327ee4
2022-04-26T09:37:42.366011357+00:00 INFO controller::chain - height: 94869 hash 0x2df395ab24f84755dce322d318e4f842fa2809afbfa3f101c4de8bf63da4315c
2022-04-26T09:38:13.884171579+00:00 INFO controller::chain - exec_block(94869): status: Success, executed_block_hash: 0x70c61e3354f5a5f70e287425c496b546340840fbba7fdace63ca7daec7428a16
2022-04-26T09:38:37.485024930+00:00 INFO controller::chain - finalize_block: 94869, block_hash: 0x2df395ab24f84755dce322d318e4f842fa2809afbfa3f101c4de8bf63da4315c
2022-04-26T09:40:37.687122731+00:00 INFO controller::protocol::sync_manager - SyncBlockRequest: start 94870, end 94870
2022-04-26T09:40:37.691864148+00:00 INFO controller::protocol::sync_manager - sync: insert_blocks: heights = [94870] from node(0xb48afb33031d25db2e3b1deb48c6033c3fb3f42f)
2022-04-26T09:40:37.697637913+00:00 WARN controller - sync block error: ProposalCheckError, node: 0xb48afb33031d25db2e3b1deb48c6033c3fb3f42f been misbehavior_node

同步94870时,进行check_block返回ProposalCheckError

consensus日志:仅能查看到----- check_proposal_proof phash但未打印----- check_proposal_proof ok,说明check_proposal_proof执行失败,打开日志debug等级,未打印----- check_proposal_proof sender
所以怀疑:

        if Some(phash) != leader_vote.hash {
            return false;
        }

此处检查返回false

需要进一步确认

ps. 确认的信息如下:

  1. 当时资源非常紧张,通过controller日志可以看出在没有交易的情况下,出块间隔达到1分钟以上
  2. 硬盘未出现溢出

默认的grpc端口不一致

USAGE:
    consensus run [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -p, --port <grpc-port>    Sets grpc port of this service [default: 50001]

共识微服务的默认gRPC端口应该为50003。

单个共识节点不出块

2022-07-26T11:09:18.012812087+00:00 INFO consensus::cita_bft - now 1658833758.012805489s start time 1658833757.988716777s interval 3000 commit height 259
2022-07-26T11:09:19.877557782+00:00 INFO consensus::cita_bft - recv to BftSvrMsg::Conf height: 259
2022-07-26T11:09:19.877588068+00:00 INFO consensus::cita_bft - new_round_start_with_added_time added time 0ns self Bft { h: 260, r: 0, s: Propose, stime: 1658833757.988716777s }
2022-07-26T11:09:19.880341424+00:00 WARN consensus::cita_bft - not find locked proposal?

第一条日志之后,是进入了高度259的commit wait阶段,因为还没有达到3s出块间隔,设置了超时定时器。
本来应该在超时定时器触发的时候把259高度的信息清掉。
但是因为恰好这时controller重启了,重新发送了BftSvrMsg::Conf消息。
bft收到这个消息后就直接进入了260高度,这时之前高度的lock等信息还在,所以走入了错误分支。

start error when I use -c parameter

error: Found argument '/etc/cita-cloud.d/config.toml' which wasn't expected, or isn't valid in this context

USAGE:
    consensus run [OPTIONS]

For more information try --help

image tag: consensus_bft:v6.3.2-alpha.1

RUSTSEC-2020-0159: Potential segfault in `localtime_r` invocations

Potential segfault in localtime_r invocations

Details
Package chrono
Version 0.4.19
URL chronotope/chrono#499
Date 2020-11-10

Impact

Unix-like operating systems may segfault due to dereferencing a dangling pointer in specific circumstances. This requires an environment variable to be set in a different thread than the affected functions. This may occur without the user's knowledge, notably in a third-party library.

Workarounds

No workarounds are known.

References

See advisory page for additional details.

RUSTSEC-2020-0036: failure is officially deprecated/unmaintained

failure is officially deprecated/unmaintained

Details
Status unmaintained
Package failure
Version 0.1.8
URL rust-lang-deprecated/failure#347
Date 2020-05-02

The failure crate is officially end-of-life: it has been marked as deprecated
by the former maintainer, who has announced that there will be no updates or
maintenance work on it going forward.

The following are some suggested actively developed alternatives to switch to:

See advisory page for additional details.

废弃BFT

先在controller里预埋bft to overlord的修改。

然后按照通用升级方案将原来是bft的链切换到overlord。


  1. controller增加danger配置项,并在get node status里查询danger目前的值。

RUSTSEC-2020-0071: Potential segfault in the time crate

Potential segfault in the time crate

Details
Package time
Version 0.1.43
URL time-rs/time#293
Date 2020-11-18
Patched versions >=0.2.23
Unaffected versions =0.2.0,=0.2.1,=0.2.2,=0.2.3,=0.2.4,=0.2.5,=0.2.6

Impact

Unix-like operating systems may segfault due to dereferencing a dangling pointer in specific circumstances. This requires an environment variable to be set in a different thread than the affected functions. This may occur without the user's knowledge, notably in a third-party library.

The affected functions from time 0.2.7 through 0.2.22 are:

  • time::UtcOffset::local_offset_at
  • time::UtcOffset::try_local_offset_at
  • time::UtcOffset::current_local_offset
  • time::UtcOffset::try_current_local_offset
  • time::OffsetDateTime::now_local
  • time::OffsetDateTime::try_now_local

The affected functions in time 0.1 (all versions) are:

  • at
  • at_utc

Non-Unix targets (including Windows and wasm) are unaffected.

Patches

Pending a proper fix, the internal method that determines the local offset has been modified to always return None on the affected operating systems. This has the effect of returning an Err on the try_* methods and UTC on the non-try_* methods.

Users and library authors with time in their dependency tree should perform cargo update, which will pull in the updated, unaffected code.

Users of time 0.1 do not have a patch and should upgrade to an unaffected version: time 0.2.23 or greater or the 0.3. series.

Workarounds

No workarounds are known.

References

time-rs/time#293

See advisory page for additional details.

bft出块慢

node0的controller日志:

2022-09-27T23:11:06.000949693+00:00 INFO controller::chain - finalize_block height: 120
...
2022-09-27T23:12:24.275782980+00:00 INFO controller::chain - commit_block height: 121

120之后过了80s才出了121

查看node0共识的日志:

2022-09-27T23:11:06.567754611+00:00 WARN consensus::cita_bft - Proc proposal not find proposal h: 121 r: 0

h 121 r 0 没有收到proposal。
当时是4个共识节点,proposer应该是node1,查看node1的共识日志:

2022-09-27T23:11:00.756446174+00:00 INFO consensus::cita_bft - recv to BftSvrMsg::Conf height: 119
2022-09-27T23:11:00.756481105+00:00 INFO consensus::cita_bft - new_round_start_with_added_time added time 0ns self Bft { h: 120, r: 0, s: Propose, stime: 1664320256.014378431s }
2022-09-27T23:11:00.759527035+00:00 WARN consensus::cita_bft - Proc proposal not find proposal h: 120 r: 0
2022-09-27T23:11:03.368001668+00:00 INFO consensus::cita_bft - handle_proposal h: 120 r: 0 hash 0x97230b66ba7602b5ff844d97ba9a7ecc8d047f06ebe67c72aaa6b42c2b9b1881, self: Bft { h: 120, r: 0, s: NewView, stime: 1664320260.759481638s }
2022-09-27T23:11:03.368032734+00:00 WARN consensus::cita_bft - Handle proposal Bft { h: 120, r: 0, s: NewView, stime: 1664320260.759481638s } get old proposal
2022-09-27T23:11:03.368047360+00:00 WARN consensus::cita_bft - process_network error: Engine error (The vote message is delayed height: 120,round: 0)
2022-09-27T23:11:04.064382017+00:00 WARN consensus::cita_bft - Follower proc prevote proposal None not equal hash 0x97230b66ba7602b5ff844d97ba9a7ecc8d047f06ebe67c72aaa6b42c2b9b1881 lock_round None
2022-09-27T23:11:04.064636715+00:00 INFO consensus::cita_bft - new_round_start_with_added_time added time 0ns self Bft { h: 120, r: 1, s: Propose, stime: 1664320260.759481638s }
2022-09-27T23:11:04.064741055+00:00 WARN consensus::cita_bft - New proposal self_proposal is none Bft { h: 120, r: 1, s: Propose, stime: 1664320260.759481638s }
2022-09-27T23:11:04.064903387+00:00 INFO consensus - consensus to controller : GetProposalReq 
2022-09-27T23:11:04.068361232+00:00 INFO consensus::cita_bft - recv from controller, GetProposalRes height 120
2022-09-27T23:11:04.069199825+00:00 INFO consensus::cita_bft - recv_new_height_proposal h: 120 hash 0xadad5ae86095d79bb5177bf4396689686927acff7a532312616001eacbff6a14 self Bft { h: 120, r: 1, stime: 1664320260.759481638s, s: ProposeWait, , proposal: None,lock_round: None, last_commit_round: None, is_consensus_node: true, }
2022-09-27T23:11:04.071607052+00:00 INFO consensus::cita_bft - New proposal proposal Bft { h: 120, r: 1, stime: 1664320260.759481638s, s: ProposeWait, , proposal: Some(0xadad5ae86095d79bb5177bf4396689686927acff7a532312616001eacbff6a14),lock_round: None, last_commit_round: None, is_consensus_node: true, }
2022-09-27T23:11:04.073350736+00:00 INFO consensus::cita_bft - the leader is me, h: 120 r: 1
2022-09-27T23:11:08.613282618+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0x4d6dd7ba39a7f0eb05f28a86865e84d8571329f0,
2022-09-27T23:11:08.613428117+00:00 WARN consensus::cita_bft - process_network error: Engine error (The vote message is future height: 121 round: 0)
2022-09-27T23:11:08.962629057+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0xefbb0a6f99f2060a5b62dec66aaf3fc108d2dd3b,
2022-09-27T23:11:08.962666588+00:00 WARN consensus::cita_bft - process_network error: Engine error (The vote message is future height: 121 round: 0)
2022-09-27T23:11:08.964198446+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0xf7f184b354658ab88a035820309eebcc599e9842,
2022-09-27T23:11:08.964322843+00:00 WARN consensus::cita_bft - process_network error: Engine error (The vote message is future height: 121 round: 0)
2022-09-27T23:11:44.604305432+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0x4d6dd7ba39a7f0eb05f28a86865e84d8571329f0,
2022-09-27T23:11:44.604356989+00:00 WARN consensus::cita_bft - process_network error: Engine error (Author 0x4d6dd7ba39a7f0eb05f28a86865e84d8571329f0 issued too many blocks.)
2022-09-27T23:11:44.967225085+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0xf7f184b354658ab88a035820309eebcc599e9842,
2022-09-27T23:11:44.967282424+00:00 WARN consensus::cita_bft - process_network error: Engine error (Author 0xf7f184b354658ab88a035820309eebcc599e9842 issued too many blocks.)
2022-09-27T23:11:44.980093717+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0xefbb0a6f99f2060a5b62dec66aaf3fc108d2dd3b,
2022-09-27T23:11:44.980225402+00:00 WARN consensus::cita_bft - process_network error: Engine error (Author 0xefbb0a6f99f2060a5b62dec66aaf3fc108d2dd3b issued too many blocks.)
2022-09-27T23:12:20.594346587+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0x4d6dd7ba39a7f0eb05f28a86865e84d8571329f0,
2022-09-27T23:12:20.594428596+00:00 WARN consensus::cita_bft - process_network error: Engine error (Author 0x4d6dd7ba39a7f0eb05f28a86865e84d8571329f0 issued too many blocks.)
2022-09-27T23:12:20.969756037+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0xf7f184b354658ab88a035820309eebcc599e9842,
2022-09-27T23:12:20.969799102+00:00 WARN consensus::cita_bft - process_network error: Engine error (Author 0xf7f184b354658ab88a035820309eebcc599e9842 issued too many blocks.)
2022-09-27T23:12:20.992648906+00:00 INFO consensus::cita_bft - Handle message hanle newview: height 121, round 0, sender 0xefbb0a6f99f2060a5b62dec66aaf3fc108d2dd3b,
2022-09-27T23:12:20.992688599+00:00 WARN consensus::cita_bft - process_network error: Engine error (Author 0xefbb0a6f99f2060a5b62dec66aaf3fc108d2dd3b issued too many blocks.)
2022-09-27T23:12:22.545448217+00:00 INFO consensus::cita_bft - ----- check_proposal_proof phash 0x97230b66ba7602b5ff844d97ba9a7ecc8d047f06ebe67c72aaa6b42c2b9b1881 h: 120 round 0
2022-09-27T23:12:22.551060559+00:00 INFO consensus::cita_bft - ----- check_proposal_proof ok
2022-09-27T23:12:22.576698691+00:00 INFO consensus::cita_bft - recv to BftSvrMsg::Conf height: 120
2022-09-27T23:12:22.576753107+00:00 INFO consensus::cita_bft - new_round_start_with_added_time added time 0ns self Bft { h: 121, r: 0, s: Propose, stime: 1664320260.759481638s }
2022-09-27T23:12:22.582977447+00:00 INFO consensus::cita_bft - new_round_start_with_added_time added time 0ns self Bft { h: 121, r: 1, s: Propose, stime: 1664320342.580330897s }
2022-09-27T23:12:22.583014381+00:00 WARN consensus::cita_bft - Proc proposal not find proposal h: 121 r: 1
2022-09-27T23:12:22.594277249+00:00 INFO consensus::cita_bft - Send newviewRes  h: 121 round r: 0
2022-09-27T23:12:22.594312466+00:00 WARN consensus::cita_bft - process_network error: Engine error (The vote message is delayed height: 121,round: 0)
2022-09-27T23:12:22.597685306+00:00 INFO consensus::cita_bft - Send newviewRes  h: 121 round r: 0
2022-09-27T23:12:22.597717269+00:00 WARN consensus::cita_bft - process_network error: Engine error (The vote message is delayed height: 121,round: 0)
2022-09-27T23:12:22.599959435+00:00 WARN consensus::cita_bft - process_network error: Engine error (Invalid Time Interval)
2022-09-27T23:12:22.601751097+00:00 WARN consensus::cita_bft - process_network error: Engine error (Invalid Time Interval)
2022-09-27T23:12:22.601863242+00:00 INFO consensus::cita_bft - handle_proposal h: 121 r: 1 hash 0x931e6f047f647b6de1f3abc54aa53bb23f05ddd1fe99b1deae7a02b3ce77b6f3, self: Bft { h: 121, r: 1, s: ProposeWait, stime: 1664320342.580330897s }
2022-09-27T23:12:22.604926661+00:00 WARN consensus::cita_bft - process_network error: Engine error (Controller not yet check the proposal.)
2022-09-27T23:12:22.604987156+00:00 INFO consensus - consensus to controller, CheckProposalReq h: 121 r: 1
2022-09-27T23:12:22.609426375+00:00 INFO consensus::cita_bft - recv from controller, CheckProposalRes h: 121, r: 1 res true
2022-09-27T23:12:22.617980613+00:00 INFO consensus::cita_bft - follower_proc_proposal h: 121 r: 1 self: Bft { h: 121, r: 1, s: ProposeWait, stime: 1664320342.580330897s }
2022-09-27T23:12:24.282602446+00:00 INFO consensus::cita_bft - gennerate proof ok Bft { h: 121, r: 1, stime: 1664320342.580330897s, s: PrecommitWait, , proposal: Some(0x931e6f047f647b6de1f3abc54aa53bb23f05ddd1fe99b1deae7a02b3ce77b6f3),lock_round: Some(1), last_commit_round: Some(1), is_consensus_node: true, }
2022-09-27T23:12:24.283736393+00:00 INFO consensus - consensus to controller : CommitBlock
2022-09-27T23:12:24.297048035+00:00 INFO consensus::cita_bft - recv from control, CommitBlockRes(121)
2022-09-27T23:12:24.297075351+00:00 INFO consensus::cita_bft - now 1664320344.29706581s start time 1664320342.580330897s interval 3000 commit height 121

情况大致如下:
node1进h: 120 r: 0太早了,过了3s node0才把h 120 r 0 的 proposal发过来,所以node1的h: 120 r: 0错过了,进了round1。
其他节点步调是一致的,所以在120 r 0就达成共识。
但是在高度120里,把共识节点数减到3个。因此121必须3个节点都投票才能达成共识。
因此等node1通过同步区块恢复了之后,121才达成共识,导致121高度出的很慢。

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.