diff options
46 files changed, 9366 insertions, 0 deletions
diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/.nojekyll diff --git a/docs/Access-to-Network.md b/docs/Access-to-Network.md new file mode 100644 index 0000000..25b345c --- /dev/null +++ b/docs/Access-to-Network.md @@ -0,0 +1,28 @@ +# Access Tangerine Network + +There are a few options on how to access Tangerine networks. The first is to use the public Tangerine RPC endpoint, the second one is to run a fullnode and sync the fullnode locally. + +## Public RPC Endpoints + +The public RPC endpoints are available at: + +|Network|RESTful|WebSocket|Chain ID| +|---|---|---|---| +|Mainnet|https://mainnet-rpc.tangerine-network.io|wss://mainnet-rpc.tangerine-network.io/ws|373| +|Testnet|https://testnet-rpc.tangerine-network.io|wss://testnet-rpc.tangerine-network.io/ws|374| + +Point your Tangerine/Ethereum client to this RPC endpoint and you should be able to read from and send transactions to Tangerine networks. + +## Syncing Fullnode + +The testnet could be synchronized with the following command: + +``` +gtan --testnet +``` + +If you don't know how to build the `gtan` binary, please follow the wiki page [here](Building-Tangerine.md). + +It may take a few hours before your fullnode is fully-synchronised. When it does, you can now point your Tangerine/Ethereum client to http://localhost:8545 + +Note: Tangerine's current testnet is still unstable, it might be reset at some point. If it does, you might have to remove the data directory (`$HOME/.tangerine` on Linux, and `$HOME/Library/Tangerine` on MacOS) and re-sync the node. diff --git a/docs/BP-Node-Operation-Guide.md b/docs/BP-Node-Operation-Guide.md new file mode 100644 index 0000000..dfa4675 --- /dev/null +++ b/docs/BP-Node-Operation-Guide.md @@ -0,0 +1,148 @@ +# BP Node Operation Guide + +- [BP Node Operation Guide](#bp-node-operation-guide) + - [Objective](#objective) + - [Background](#background) + - [Overview](#overview) + - [Environment Setup](#environment-setup) + - [System Requirement](#system-requirement) + - [Hardware Requirement](#hardware-requirement) + - [Software requirement](#software-requirement) + - [Software Instruction](#software-instruction) + - [Network Time Protocol Setting](#network-time-protocol-setting) + - [Network confirmation](#network-confirmation) + - [Generate Node Key](#generate-node-key) + - [Register & Run your Node](#register--run-your-node) + - [Troubleshooting](#troubleshooting) + - [Operation](#operation) + - [Mining Mechanism](#mining-mechanism) + - [Tangerine Mining Economy and Mining Rewards](#tangerine-mining-economy-and-mining-rewards) + + +## Objective +The document will contain essential instructions and knowledge for a node operator to successfully run a Tangerine BP node. + +## Background +For node operator to easily establish a Tangerine BP node and continuously run the node for mining rewards, Tangerine foundation provides the well-designed software supporting the mining mechanism on Tangerine blockchain. + +## Overview +The guide has 3 sections, providing the required knowledge for a node operator to: Set up node, run software, and collect mining rewards. + +## Environment Setup +How to set up AWS/GCP server? + +For AWS, please follow https://docs.aws.amazon.com/quickstarts/latest/vmlaunch/welcome.html + +For GCP, please follow https://cloud.google.com/compute/docs/quickstart-linux + +### System Requirement +Running Tangerine BP node has the following requirement: + +### Hardware Requirement + +| Tier | CPU | Memory | Bandwidth | Estimated Cost | +| --- | --- | --- | --- | --- | +| Minimum | 4 Cores 2.0+ GHz | 8 GB | 200Mbps | 200~400 USD/mth | +| Recommend| 8 Cores 2.0+ GHz | 16 GB| 200Mbps | 600~800 USD/mth | + +### Software requirement + - OS: Linux 64 bit. + - Docker image: byzantinelab/go-tangerine + - Docker + - Public IP or behind UPnP-enabled router + +## Software Instruction + +### Network Time Protocol Setting + +NTP (Network Time Protocol) is required to keep the system clock in-synced. +Install `ntpd` or `chronyd` in Linux; `chronycontrol` in macOS. +Start it and it will synchronize the local time automatically. + +### Network confirmation + +Please make sure `TCP/30303` and `UDP/30303` is exposed, or else your node is likely to be disconnected from the reset of the network. + + +### Generate Node Key +A node key is required to operate a BP node. Run the following command to generate a node key: + + docker run -v $PWD:/mnt -it byzantinelab/tangerine-tools \ + nodekey generate /mnt/node.key + +This show output content similar to the following + + Node Address: 0x93aA8C9C77De627E665F0b4015B7271B9Be89E83 + Public Key:0x046272a157cbffa00677be00b08c9d47f295539b07e53360754579ad5e933a638ba58dcf850484e7d40b8bc163a920082b2500ee54968db7155c6231c7e4eed592 + +Please store the address and public key which will be used to register a fullnode. +A file node.key can be found under the current working directory. node.key is very important as it contains the node private key. Please save this file securely. + +### Register & Run your Node +1. Start the BP node. Use the following command to launch the BP node: + +``` +docker run --restart always \ + -v $PWD:/mnt \ + -p 30303:30303/tcp \ + -p 30303:30303/udp \ + -it byzantinelab/go-tangerine:latest \ + --bp \ + --nodekey=/mnt/node.key \ + --datadir=/mnt/datadir \ + --syncmode=fast\ + --cache=1024 \ + --gcmode=archive \ + (--testnet) +``` + +The parameter `testnet` is only for the testnet of Tangerine Network. + +Please make sure you have enough disk space in the current working directory + +For more detail instruction about `gtan`, go to https://github.com/byzantine-lab/go-tangerine or use + + docker run -v $PWD:/mnt -it byzantinelab/go-tangerine --help + +2. Install [Chrome or Firefox wallet extension](Create-Wallet.md). +3. Send some TAN to your node key address, 500 TAN should suffice. These TAN are required for the node to send transaction and interact with the consensus protocol. You need to replenish them if it ran out. +4. Send 5 ETH (Ethereum mainnet Ether, use Rinkeby Ether for testnet) to your node key address. This is a very **important** step. Since Tangerine relies on Ethereum mainnet to recover itself in case there is a catastrophic network failure. There are penalties if a BP node failed to propose recovery vote due to insufficient Ether in their node key address, see [Rules for node set](Rule-for-the-node-set.md) for more details. +5. Goto the [Governance contract page on Tangerine Garden](https://testnet.tangerine.garden/address/0x246FcDE58581e2754f215A523C0718C4BFc8041F). +6. Navigate to the `Write` tab and select `register` from the dropdown menu. + +7. Fill in the information like below; currently, you need 1M TAN to run a BP node. If you don't have enough testnet TAN, ask @wnhuang (telegram) for it. + + - Node Public Key (the public key generated above and should not duplicate) + - Name of the node (maximum length: 32 bytes) + - Contact email (maximum length: 32 bytes) + - Node Location (maximum length: 32 bytes) + - Website URL (maximum length: 128 bytes) + +![Register in Governance Contract Page](https://i.imgur.com/hlaXgyS.png) +The user whose stake is locked (bought TAN coin in private-sale), please contact Tangerine Foundation and provide the information below. + +7. Hit send to register your node. + +After this, you are successfully staked and the configuration will start to take effect after 2 epochs (2400 blocks). + +Note that, the account of node.key and the account to send TAN coin to governance contract are not necessary to be the same. We strongly suggest using different keys to manage the risk. + + +### Troubleshooting + +Here is a check list for trouble shooting issues with fullndoe: + +1. Does the node have Public IP? or is it behind router that has UPnP support? +2. Firewall configuration for TCP/30303 and UDP/30303 are allowed. +3. NTP (Network Time Protocol) services installed? + +### Operation + +A BP node need to be online at all time, but since network between each BP nodes could be unstable, it's possible for connections between peers to be temporarily disconnected. In this case, DKG setup might fail and your node could be fined. Please read [here](Rules-for-the-node-set.md#Penalty) for more explaination on the penalty. + +## Mining Mechanism + +### Tangerine Mining Economy and Mining Rewards +Please read [this document](Cryptoeconomics.md) + +As an example, initially, each node can expectedly mine 1M * 18.75% = 187.5K TAN coin per year (before total minted tokens hit 1.5B TAN). diff --git a/docs/Blockchain-Comparison.md b/docs/Blockchain-Comparison.md new file mode 100644 index 0000000..c7ce7b0 --- /dev/null +++ b/docs/Blockchain-Comparison.md @@ -0,0 +1,276 @@ +Tangerine Comparison to Other Blockchain +== +### Introduction +This document explains how Tangerine is different compared to other blockchain infrastructures. We do our best to explain the main differences, but still, we have the following principles: +1. We will not dive into details of other projects. We only focus on the differences. For the details, please refer to their websites and whitepapers. +2. The comparison is based on our current understanding, and projects can be updated frequently. We will update this document if necessary. + +### Definition +- Node in this document is a validator or a full node in the network. +- <img src="https://latex.codecogs.com/svg.latex?T_{network}" />: network delay between nodes +- <img src="https://latex.codecogs.com/svg.latex?n" />: number of nodes +- <img src="https://latex.codecogs.com/svg.latex?b" />: number of blocks to be confirmed +- <img src="https://latex.codecogs.com/svg.latex?f" />: ack frequency +- For smart contract column: + - O: Supprted + - X: Not supported + - △: Not supported for now, but is able to support + +## Table of Contents + +| Project | Throughput (TPS) | Latency (seconds) | Data Structure | Consensus | Smart Contract | +| --- | --- | --- | ------------- | --- | --- | +|[Tangerine](#tangerine)|10K|1|chain|Byzantine agreement|O| +|[Algorand](#algorand)|875|< 60|chain|Byzantine agreement|△| +|[Bitcoin](#bitcoin)|7|3600|chain|longest chain rule|X| +|[Cardano](#cardano)|250|300|chain|Ouroboros|O| +|[Conflux](#conflux)|6400|270|DAG|GHOST|△| +|[Dfinity](#dfinity)|500 ~ 1000|5 ~ 10|chain|Dfinity|O| +|[EOS](#eos)|3K|165|chain|longest chain & Byzantine fault tolerance|O| +|[Ethereum](#ethereum)|20|360|chain|longest chain|O| +|[Hashgraph](#hashgraph)|200K|20|DAG|Hedera|O| +|[Hyperledger](#hyperledger)|4K|< 1|chain|pluggable|O| +|[IOTA](#iota)|500 ~ 800|> 180|DAG|longest chain rule|X| +|[Kadena](#kadena)|10K|20|DAG|Chainweb|O| +|[NANO](#nano)|7000|1|DAG|DPoS voting|X| +|[Omniledger](#omniledger)|6K|10|chain|ByzCoinX|△| +|[Ontology](#ontology)|5K|20|DAG|Ontorand|O| +|[Orbs Helix](#orbs-helix)|10|NA|chain|PBFT|O| +|[Phantom](#phantom)|NA|NA|DAG|greedy selection algorithm|△| +|[Radix](#radix)|3.5|5|chain|logical clock|O| +|[Snowflake](#snowflake)|1300|4|DAG|Avalanche|△| +|[Spectre](#spectre)|NA|1 ~ 10|DAG|block voting algorithm|X| +|[Stellar](#stellar)|1K ~ 10K|2 ~ 5|chain|Stellar Consensus|O| +|[Tendermint](#tendermint)|NA|1 ~ 3|chain|PBFT|△| +|[Thunderella](#tendermint)|NA|1.5|chain|BFT + longest chain|△| +|[TON](#ton)|M+|5|DAG|BFT|O| +|[Vite](#vite)|NA|10|DAG|longest chain|O| +|[Zilliqa](#zilliqa)|3K|10 ~ 20|chain|PBFT|O| + +## Tangerine +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|10K|1|chain|Tangerine Byzantine agreement|O| + +Tangerine is a scalable, low-latency, energy efficient and inter-chain operable DApp ecosystem. Tangerine uses an efficient Byzantine agreement as its main consensus algorithm, of which throughput can scale linearly with the number of nodes while latency remains nearly constant. With the adoption of verifiable random function, Tangerine can provide high performance while keeping the network decentralized (~ 100K nodes). With such high throughput and low latency, practical DApp can finally be developed and widely used. + +## Algorand +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|875|< 60|chain|Byzantine agreement|△| + +Algorand is designed for a large population ( ~ 500K nodes). They use a verifiable random function to protect nodes from DDoS attack, and it is the lottery that decides who have the right to propose a block or to vote for each round. + +The consensus of Algorand is based on Byzantine agreement among samples from the whole set of nodes. This is the reason why Algorand can only tolerate less than one-third of the total number of nodes. For example, if it sets 1/5 as the maximum ratio of Byzantine nodes among all nodes, the ratio of Byzantine nodes in samples can be bounded by 1/3 with high probability. + +They use gossip mechanism that costs a latency of <img src="https://latex.codecogs.com/svg.latex?O(log(n))*T_{network}" /> for each message, which means its confirmation time becomes longer when the number of nodes increases and scatters around the world. With this limitation, the confirmation time will be around one minute if the number of nodes is expected to be 500K. Another factor that will affect the confirmation time is Byzantine behavior. If a Byzantine node wins the lottery and becomes a leader, the process of the Byzantine agreement will need more round to converge. On the other hand, Tangerine's confirmation time is not affected by Byzantine behavior as long as the number of Byzantine nodes is less than one-third of total nodes. + +If Algorand wants to increase its throughput, it must increase block size. However, increasing block size causes a longer network delay, increasing the confirmation time. This means Algorand is lack of scalability. On the other hand, Tangerine increases throughput by increasing the number of nodes without affecting the confirmation time. + +## Bitcoin +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|7|3600|chain|longest chain rule|X| + +Bitcoin is the first cryptocurrency that starts the era of blockchain. It is the most well-known and widely used cryptocurrency. However, it is infamous for its long confirmation time, low TPS and high transaction fee. Tangerine solves all of them and at the same time provides DApp functionality, which Bitcoin does not have. + +## Cardano +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|250|300|chain|Ouroboros|O| + +Cardano is the first project that provides a concrete mathematical proof on the security of PoS blockchain. Besides PoS, they also propose other promising ideas such as unbiased randomness with the commit-reveal scheme and using Nash Equilibrium to prevent selfish mining attack. However, its chain-based structure naturally limits its throughput, since chain-based structure can only process block linearly, and can be proved that it can not scale. + +Another problem in Cardano consensus is that it highly depends on time synchronization. If some honest nodes are desynchronized (for example, NTP service hijack by an attacker), they do not know when is the starting time of a slot and will be treated as fail-stop nodes. They claimed desynchronized nodes could be corrected by some method introduced in the future, but it is not implemented yet. + +## Conflux +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|6400|270|DAG|GHOST|△| + +Conflux is a graph-based PoW consensus based on GHOST protocol that fixed the Phantom blockchain. Conflux uses GHOST protocol to select the main chain in a graph and produces a total ordering of the graph by the main chain. Thus, it is generalized Bitcoin consensus, and they also point out that the bias problem in Phantom blockchain. + +However, the latency is bounded by its PoW mechanism. It needs to wait for a period to select the correct and consistent main chain with high probability. Even if it switched to a PoS mechanism, the latency would still be unacceptably long since the GHOST protocol is a kind of longest chain rule consensus. + +## Dfinity +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|500 ~ 1000|5 ~ 10|chain|Dfinity|O| + +Dfinity is a permissioned blockchain and is designed for a large population (around 10K of nodes). Dfinity contains a randomness beacon which generates new randomness by a VRF (verifiable random function) with information from a new confirmed block. They use the randomness to select a leader and electors for a round. By hypergeometric distribution, Dfinity only samples hundred of nodes to notary a block instead of using all nodes, and this is correct with high probability. However, this reduces the tolerance ability to Byzantine nodes. For example, to achieve the majority of nodes is non-Byzantine with probability less than <img src="https://latex.codecogs.com/svg.latex?2^{-40}">, it needs to sample at least 423 nodes from 10K nodes with maximum 1/3 Byzantine nodes. +However, Dfinity is chain-based, so its throughput is limited. + +## EOS +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|3K|165|chain|longest chain & Byzantine fault tolerance|O| + +EOS reaches high throughput and low latency. They have 21 so-called "supernodes," which are considered not decentralized. Also, at the time of writing, its Byzantine fault tolerance consensus is not implemented yet, so the confirmation time is about 165 seconds, not 1 or 2 seconds as they claimed. + +## Ethereum +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|20|360|chain|longest chain|O| + +Ethereum is the first blockchain system that has a complete DApp ecosystem. It has a throughput higher and latency lower than Bitcoin, but still not enough for daily usages such as payment or gaming. A popular DApp can block the whole system, causing high transaction fee. Also, the latency now (several minutes) is not acceptable for real-time applications. + +## Hashgraph +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|200K|20|DAG|Hedera|O| + +The consensus of Hashgraph is adapted Byzantine agreement on a graph, on the other hand, the core of Tangerine consensus is a responsive Byzantine agreement algorithm. Their round-based structure costs a latency of <img src="https://latex.codecogs.com/svg.latex?O(log(n))*T_{network}" /> for each round, which means its confirmation time becomes longer when the number of nodes increases. With this limitation, it cannot be fully decentralized, or the confirmation time can be minutes. Also, the liveness is not guaranteed in Hashgraph. Only correctness proof is provided. With Byzantine nodes presented in its network, it is possible that Hashgraph does not output any block. Meanwhile, Tangerine's confirmation time does not increase when the number of nodes increases. Since Tangerine consensus has responsiveness, the confirmation time only depends on the actual network speed, not some predefined paramters. + +## Hyperledger +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|4K|< 1|chain|pluggable|O| + +Hyperledger (specifically, Hyperledger Fabric) is a distributed ledger designed for enterprise use. It should be permissioned, low-latency, high-throughput and provides private transaction functionalities. Its consensus is modularized and pluggable. It can choose among consensus engines/algorithms such as Tendermint, PBFT, Kafka ordering or RAFT. + +It is much easier to address consensus problem in a permissioned consortium settings with high throughput and low latency because the assumption of the environment is: the number of nodes is fixed, each identity is known, the goal of all nodes is the same, and the network environment is stable and fast, but the node does not fully trust to each other. It does fit for enterprises to use such settings, while Tangerine aims to be more open and decentralized, providing high throughput and low latency at the same time. + +## IOTA +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|500 ~ 800|> 180|DAG|longest chain rule|X| + +IOTA follows the longest chain rule on a graph: a node randomly chooses and verifies two previous blocks and attaches its block to them. A block is confirmed if enough number of blocks followed it and the length of the connected chain is the longest. +However, the rule is inefficient because the confirmation time is not guaranteed by a specific bound. Moreover, a block might be invalid if it is attached to a block that contains conflict transactions. That block has to be re-attached to other blocks. This causes a very long confirmation time. Furthermore, IOTA does not support smart contract due to the lack of total ordering among all blocks. + +## Kadena +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|10K|20|DAG|Chainweb|O| + +Kadena aims to solve the scalability issue of blockchain. Each chain in Kadena includes others' block headers, forming a so-called Chainweb. Chainweb processes transactions in parallel. To perform cross-chain transactions, one has to provide Merkle proof to smart contract, and assets will be deleted from source chain and re-created on destination chain. Kadena also analyzes peer header relationships and uses specifically designed graphs that have a small diameter and large order to achieve low latency and high throughput. + +The latency of Chainweb is <img src="https://latex.codecogs.com/svg.latex?O(r)"/>, where <img src="https://latex.codecogs.com/svg.latex?r"/> is the diameter of a graph. When it scales up and increases the number of chains, the diameter of the graph also becomes larger, causing the latency to increase. Another problem is when proposing a block on a chain. The block has to include its peer's block headers. This means block proposing is blocking and not efficient, while in Tangerine, a block actively acks any other newly proposed blocks, achieving fast non-blocking block proposing. + +## NANO +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|7000|1|DAG|DPoS voting|X| + +NANO is the first project that introduces blocklattice as their data structure. Each account has its blockchain, and a transaction it proposed is recorded on its blockchain. When a blockchain fork happens, NANO starts DPoS voting to resolve it. + +Tangerine chain structure is entirely different from NANO's. In Tangerine, instead of every account having its blockchain, each validator has a blockchain. This could save a lot of memory space compared to NANO. In Tangerine, each vertex is a block, while in NANO, each vertex is half of a transaction (send tx or recv tx). From our viewpoint, their blocklattice is more like "tx-lattice," not blocklattice, and we consider blocklattice a general term that can be used by other projects, just like blockchain, since it is just a type of DAG. + +Tangerine's consensus algorithm is also completely different from NANO's. Validators in Tangerine rely on Tangerine fast Byzantine agreement algorithm to decide sequence of blocks and transactions, while NANO does not have consensus on order of transactions. Without ordering transactions, it can not support smart contract. Another problem is its DPoS to resolve fork. The voting process NANO used to resolve fork is mysterious. In its whitepaper, there is no detail about the voting process. The only thing we know is a majority voting with 4 rounds. Without further detail and security proof, we find it hard to believe that NANO is secure. Also, NANO needs PoW to prevent spam (penny) attack, increasing the cost of attack but also limiting its throughput and increasing its latency. + +## Omniledger +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|6K|10|chain|ByzCoinX|△| + +Omniledger aims to solve scalability problem without sacrificing security and decentralization. Its primary approach is sharding, which allows the throughput to scale linearly with the number of nodes. Omliledger also provides nice features such as ledger pruning, cross-shard transaction, and trust-but-verify validation. + +The problem of Omniledger is that its latency could be large in a fully decentralized setting. The reason is that it uses ByzCoinX (which is an optimization of PBFT-like consensus algorithm) for intra-shard consensus and Atomix (DB-like atomic broadcast) for inter-shard transactions. This means the group size in a shard for communication cannot be too large, or the communication cost and latency will be large. To increase the number of nodes with limited shard size, the number of shards will increase, and the needs for cross-shard transactions will also increase. With atomic broadcast, a cross-shard transaction has to wait for every involved shard to be confirmed, and even a single shard failed will cause the transaction to fail. In Tangerine, transactions only need to enter one shard and will be output immediately. + +Omniledger also sacrifices some of the security. According to hypergeometric distribution, if the sampled Byzantine nodes in a shard must be less than one third, one can only tolerate Byzantine nodes much less than one third in the whole network, or sampling cannot be successful with high probability. This is why the number of Byzantine nodes Omniledger can tolerate is one fourth, not one-third of total nodes. + +## Ontology +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|5K|20|DAG|Ontorand|O| + +Ontology consensus algorithm Ontorand uses randomness from the last block to generate new block proposer and validators. Its Byzantine agreement voting process (although not detailed enough) looks extremely similar to Algorand. Its verifiable random function which generates randomness in a block is exactly the same as Algorand. Without any citation and improvement from Algorand, Ontorand is nothing but a copycat. For the comparison to Algorand, please reference [here](#algorand). + +## Orbs Helix +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|10|NA|chain|PBFT|O| + +The top priority of Helix is fairness. It uses VRF (verifiable random function) as an unbiased random source to elect committee and leader. When running its core consensus (PBFT), all transactions are encrypted by users using threshold encryption. This means there is no way a node can censor or prioritize any transaction. After consensus is reached, the content of a block is then decrypted, and transactions are executed. Thus, the order of transactions cannot be biased, achieving fairness. Helix also uses VRF to decide which transaction can be put into a block. Because nodes cannot decide which transactions to be put into a block, transaction fees can be set to a constant. + +Unfortunately, fairness does not come without cost. Threshold encryption not only increases computational cost but needs an extra phase of decryption. This increase the latency. What's worse, its chain structure is not scalable. To solve the scalability problem, Orbs introduces "intelligent sharding" (which we did not find any technical detail). A recent simulation shows that Helix has only 10 TPS (with unknown latency). With 100 shards, it can reach 1000 TPS, while Tangerine has 1M+ TPS with a hundred nodes in one shard. + +## Phantom +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|NA|NA|DAG|greedy selection algorithm|△| + +Phantom is a DAG-based blockchain which is generalized from Bitcoin's longest chain rule on a chain to a DAG. Phantom is a proposal for Spectre, and they proposed a greedy algorithm called ghostDAG protocol to achieve total ordering. However, they did not prove the correctness and liveness of their algorithm or provide the simulation results about Phantom in the distributed setting. Another liveness attack on Phantom was individually proposed by the work from Li et al. and the work from Kiayias and Panagiotakos. They also claimed they would try to combine Phantom and Spectre in the future. We will update the information if they provide new and correct results. + +In Tangerine, the correctness and liveness of Tangerine Byzantine agreement are both strictly proved. + +## Radix +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|3.5|5|chain|logical clock|O| + +Radix uses sharding technique to increase throughput. In order to reach consensus among different shards, a transaction needs to be gossipped and be validated by many nodes. Each node provides its local logical clock and appends its value to the transaction. Nodes can then use this logical clock vector to decide partial ordering between two conflict transactions. In case of a concurrent set, a node finds other transactions from its local storage or from its peer trying to decide partial ordering of transactions. + +There is a fundamental problem in Radix: a partial ordering can never become total ordering without consensus algorithm. Some partial ordering of transactions in Radix can be decided by vector timestamps, but no matter how many transactions are involved, there always exists some cases that concurrent set can never be resolved. In other words, orders of some transactions may never be decided and will not be output by the system. What's worse, when a network is shortly partitioned or has a long network delay, nodes can have different local views. Since a node decides an ordering from other transactions from its local view, this will cause different ordering among nodes, resulting in a fork, and there is no consensus algorithm in Radix to address this issue. + +To sum up, Radix does not have consensus. It can be used in private / permissioned settings but will not work in a real network environment. + +## Snowflake +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|1300|4|DAG|Avalanche|△| + +Snowflake consensus starts from a simple coloring method, adds additional counters and rules, and finally ends up a provably probabilistic secure consensus algorithm, Avalanche. All nodes converge to the same color, which means that they will agree on the same transaction set when conflict happens. + +In order to resolve conflict transactions, nodes need to execute Avalanche algorithm on every transaction in a conflict set. So an attacker can spam the system with a large number of conflict transactions, resulting in the system to execute Avalanche algorithm hundreds of thousands of times, and the latency will grow significantly. Tangerine will not suffer from such an attack. Tangerine Byzantine agreement remains fast no matter how many conflict transactions there are. + +## Spectre +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|NA|1 ~ 10|DAG|block voting algorithm|X| + +Spectre is a DAG-based digital ledger system that uses recursive block voting to decide which conflict block should be finalized. This consensus algorithm allows participants to propose block arbitrarily fast, which means its scalability and latency is bounded by the network. However, its lack of total ordering of blocks makes it impossible to execute a smart contract. That is the reason why they propose "Phantom," a consensus that is also DAG-based but with total ordering properties. We also compare Tangerine to [Phantom](#phantom). + +## Stellar +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|1K ~ 10K|2 ~ 5|chain|Stellar Consensus|O| + +Stellar uses a generalized version of traditional Byzantine agreement protocol, which they called "federated Byzantine agreement." This consensus algorithm requires participants to choose their own quorum slices. If quorum intersection is satisfied, it is proved that all intact participants will reach consensus. + +The only concern about this kind of consensus is that whether a node can remain intact (not affected by Byzantine nodes) depends on the choice of its quorum slices. In order to have a secure configuration with fast response and stable service, it is better for a node to choose nodes set up by reliable companies or banks as quorum slices, which may lead to semi-centralization. + +## Tendermint +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|NA|1 ~ 3|chain|PBFT|△| + +Tendermint uses PBFT as their consensus algorithm. Although PBFT has low latency in permissioned settings, it can not be permissionless, because PBFT has a heavy communication cost of <img src="https://latex.codecogs.com/svg.latex?O(b*n^2)" /> due to its two-phase commit. This means when the number of nodes increases, the required bandwidth of network will also increase quadratically, limiting the number nodes. Tangerine uses cryptographic sortition sharding technique and configurable ack frequency to reduce the communication cost to <img src="https://latex.codecogs.com/svg.latex?O(f*n*log(n))" />. + +## Thunderella +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|NA|1.5|chain|BFT + longest chain|△| + +Thunderella combines two different consensus algorithms and tries to achieve high security with good performance. With less than one-fourth of the committee are Byzantine nodes, it can achieve a low latency with BFT algorithm. With more than one fourth, it can fall back to any blockchain system that can tolerate less than <img src="https://latex.codecogs.com/svg.latex?\frac{1}{2}n" /> Byzantine nodes. + +If more than one-fourth of the committee is Byzantine node, Thunderella becomes as slow as a blockchain, while Tangerine remains its low latency. Also, Thunderella is a chain-based system, and it can not scale. + +## TON +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|M+|5|DAG|BFT|O| + +TON (Telegram Open Network) is a blockchain system featuring high throughput with short confirmation time. To achieve this, they propose a new point of view called "Infinite Sharding Paradigm," which tries to push sharding to its extreme. In TON, there is a masterchain for general state finalization. Under a masterchain, there are several workchains to perform specific tasks for different cryptocurrencies and services. If a workchain is overloaded, under that it can have several shardchains to increase throughput. In each chain, validators run a BFT-based consensus algorithm with a DPoS mechanism to propose blocks. With this sharding design, TON claims it can reach several millions of TPS with 5 seconds latency. + +One significant difference between TON and Tangerine is that TON needs to run BFT consensus algorithm on several different levels of the chains. For masterchain, it requires all validators to participate in BFT algorithm. Since BFT algorithm is typically not scalable, we can only have a limited number of nodes to participate in masterchain. This can be considered a bit centralized. In Tangerine, we do not require all nodes to run a single BFT algorithm; thus we can have hundreds of thousands of nodes participating in our system. + +TON also has a finalization problem. It allows validators to modify invalid blocks without forking since it is more efficient and will only affect some history blocks. However, this design also allows an attacker to modify arbitrary history blocks if they can compromise the validator set. Typically in a system with BFT finalization, it should be impossible to modify history even if the current validator set is compromised. Even in traditional PoW scheme, launching a 51% attack and modifying history blocks has a much higher cost with low probability to success. This design may cause security issue in TON. + +## Vite +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|NA|10|DAG|longest chain|O| + +Vite mainly fixes NANO's problem we mentioned in our [comparison to NANO](#nano). It uses the same blocklattice with NANO, but additionally adds a new consensus mechanism (HDPoS) to construct a snapshot chain. This not only solves security issues in NANO but also orders transactions, making it capable to run smart contract. What's more, Vite inherits NANO's advantages, including nearly instant transactions with high TPS. + +One of the difficult challenges to use a DAG structure is to decide the ordering of transactions. Vite has a global consensus group to run a consensus algorithm to create snapshot chain. This algorithm is important because it is the key to improve NANO's disadvantages on security and lack of total ordering. Unfortunately, we can not find any detail about the algorithm in their paper and do not know how transactions on blocklattice are picked and put into snapshot chain. Is this critical process secure and fair? To address this challenges, Tangerine develops our own fast Byzantine agreement algorithm, and it is provably secure and reasonably fair. + +## Zilliqa +|Throughput (TPS)|Latency (seconds)|Data Structure|Consensus|Smart Contract| +|-|-|-|-|-| +|3K|10 ~ 20|chain|PBFT|O| + +Zilliqa is an optimized PBFT. It uses EC-Schnorr multi-signature to aggregate signatures from nodes. This reduces communication cost from <img src="https://latex.codecogs.com/svg.latex?O(n^2)" /> to <img src="https://latex.codecogs.com/svg.latex?O(n)" />. To address limited throughput in a chain-based system, Zilliqa uses sharding technique to process transactions in parallel. A specific shard collects micro blocks from normal shards to produce final blocks. + +There are several drawbacks in Zilliqa. First of all, multi-signature aggregation is computationally costly. This is not a problem with ten-second finalization time, but in sub-second finalization time, it is not feasible with a large number of nodes in a shard. Second, Zilliqa uses a specific shard running consensus protocol to combine micro blocks from other shards. This doubles the latency. In Tangerine, there is no specific shard to run another redundant consensus protocol. Tangerine uses state sharding, which means each shard only stores state related to itself. This sharding mechanism is symmetric, which means every shard has the same contribution in terms of consensus, and this is considered more fair. diff --git a/docs/Building-Tangerine.md b/docs/Building-Tangerine.md new file mode 100644 index 0000000..57a0434 --- /dev/null +++ b/docs/Building-Tangerine.md @@ -0,0 +1,10 @@ +## Installation Instructions + +**More platforms coming soon** + +Follow the appropriate link below to find installation instructions for +your platform. + +* [Installation Instructions for macOS](Installation-Instructions-for-Mac.md) +* Installation Instructions for Linux/Unix + * [Ubuntu](Installation-Instructions-for-Ubuntu.md) diff --git a/docs/Configuration-Change.md b/docs/Configuration-Change.md new file mode 100644 index 0000000..c0bc6cf --- /dev/null +++ b/docs/Configuration-Change.md @@ -0,0 +1,14 @@ +# Configuration Change + +## Overview +The configuration for Tangerine is round based configuration, which is allowed to be changed and applied in upcoming rounds on the fly without shutting down or forking the system. +Each configuration will become effective two rounds after updating. Configurable parameters including: +- MinStake: minimum stake required for becoming a bp. +- LockupPeriod: time required for funds available for withdrawing after unstake. +- MinGasPrice: minimum gas price. +- LambdaBA, LambdaDKG: period for each step for Tangerine Byzantine Agreement and Tangerine DKG protocol. +- NotaryParamAlpha, NotaryParamBeta: parameter for calculating notary set size. Refer to [Selection of notary set size](Selection-of-the-notary-set-size.md). +- RoundLength: the number of blocks in a round. +- MinBlockInterval: the minimum interval of timestamps between blocks on the blockchain. +- FineValues: penalty for not following protocol. Refer to [Rule for the Tangerine node set](Rule-for-the-node-set.md). + diff --git a/docs/Contribute-to-Tangerine-Fullnode.md b/docs/Contribute-to-Tangerine-Fullnode.md new file mode 100644 index 0000000..3ac2cc1 --- /dev/null +++ b/docs/Contribute-to-Tangerine-Fullnode.md @@ -0,0 +1,22 @@ +# Contribute to Tangerine Fullnode + +Thank you for considering to help out with the source code! We welcome contributions from +anyone on the internet, and are grateful for even the smallest of fixes! + +If you'd like to contribute to go-tangerine, please fork, fix, commit and send a pull request +for the maintainers to review and merge into the main code base. If you wish to submit more +complex changes though, please check up with the core devs first on [our gitter channel](https://gitter.im/byzantine-lab/Lobby) +to ensure those changes are in line with the general philosophy of the project and/or get some +early feedback which can make both your efforts much lighter as well as our review and merge +procedures quick and simple. + +Please make sure your contributions adhere to our coding guidelines: + + * Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). + * Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. + * Pull requests need to be based on and opened against the `dev` branch. + * Commit messages should be prefixed with the package(s) they modify. + * E.g. "eth, rpc: make trace configs optional" + +Please see the [Developers' Guide](https://github.com/byzantine-lab/go-tangerine/wiki/Developers'-Guide) +for more details on configuring your environment, managing project dependencies and testing procedures. diff --git a/docs/Create-Contract-Verification-Message.md b/docs/Create-Contract-Verification-Message.md new file mode 100644 index 0000000..afb8389 --- /dev/null +++ b/docs/Create-Contract-Verification-Message.md @@ -0,0 +1,39 @@ +Here's some sample code for creating and sending a verification transaction for your smart contract. + +```javascript +// Node Version: 10.15.1 +// NPM Version: 6.8.0 +const Web3 = require('web3'); // Version: 1.0.0-beta.37 +const EthereumTx = require('ethereumjs-tx'); // Version: 1.3.7 + + +const web3 = new Web3('https://testnet-rpc.tangerine-network.io); +const myAddress = '0x89c24a88BaD4abE0A4F5b2EB5a86db1fb323832C'; +const myPrivateKey = Buffer.from('61ce8b95ca5fd6f55cd97ac60817777bdf64f1670e903758ce53efc32c3dffeb', 'hex'); +const message = 'Tangerine-DS'; + +web3 + .eth + .getTransactionCount(myAddress) + .then((count) => { + const rawTx = { + nonce: web3.utils.numberToHex(count), + gasPrice: web3.utils.numberToHex(web3.utils.toWei('24', 'Gwei')), + gasLimit: web3.utils.numberToHex('210000'), + to: myAddress, + value: web3.utils.numberToHex('0'), + data: web3.utils.toHex(message), + }; + const tx = new EthereumTx(rawTx); + tx.sign(myPrivateKey); + return tx.serialize(); + }) + .then((serializedTx) => { + web3 + .eth + .sendSignedTransaction(`0x${serializedTx.toString('hex')}`) + .then((result) => { + console.log(result); + }); + }); +``` diff --git a/docs/Create-Wallet.md b/docs/Create-Wallet.md new file mode 100644 index 0000000..457a364 --- /dev/null +++ b/docs/Create-Wallet.md @@ -0,0 +1,43 @@ +# Create Wallet +A cryptocurrency wallet is a store to keep private keys when interacting with blockchains. Tangerine foundation provides the following browser wallets: + +- [Chrome](https://chrome.google.com/webstore/detail/tangerine-wallet/pmfboceaaldgniakejfcfkidccbiimae) +- [Firefox](https://addons.mozilla.org/en-US/firefox/addon/tangerine-wallet/) + +## Precautions +There is still no best practice in protecting private keys when holding/using cryptocurrency. What we provide is simply the most convenient way, use it at your own risk. + +### Wallet Secrets +There are three types of secrets when using a Tangerine wallet. + +#### Password +A password is required when accessing secrets through the wallet, ex. +- export the private key of one account. +- reveal seed phrases. + +#### Seed Phrases +The seed phrases composed of 12 or 24 words is used to generate private keys for newly created accounts. Since all private keys generated from one set of seed phrases are identical, it can be used to migrate your account from one computer to another. + +#### Accounts +An account in Tangerine Wallet is actually a private key, which can be used to interact with Tangerine blockchain. + +### Risks +If your computer gets hacked, the hacker might stole your account or seed phrases, and transfer your digital assets to somewhere else. + +Or you may lose your secrets for some reason. If that happened, no one but GOD can access those digital assets. + +## Install Tangerine Wallet +Please go to this [link](https://tangerine-network.io/faucet) and follow instructions to install Tangerine Wallet. If the wallet is freshly installed (not from restoration), you will get 12 **seed words**, please keep them secretly and safely. + +## Create New Accounts +When Tangerine wallet successfully installed, a default account would be created and ready to use. If you need more accounts, it can be done via Tangerine Wallet: +- click the [blockie](https://github.com/download13/blockies) image on the top-right corner. +- click **Create Account** element. +- click **Create** Button or give this account a name. + +## Restore from seed words +The accounts created on one wallet can be migrated to another computer via seed words. +- install Tangerine Wallet. Instead of creating it freshly, choose **Import with seed phrase** +- type in those seed phrases you keep secretly before. NOTE: the order of words does matter. +- setup new password. +- restore those accounts by creating them again. diff --git a/docs/Cryptoeconomics.md b/docs/Cryptoeconomics.md new file mode 100644 index 0000000..bcc6c18 --- /dev/null +++ b/docs/Cryptoeconomics.md @@ -0,0 +1,149 @@ +# Tangerine Network Cryptoeconomics + +Tangerine Foundation Last Modified 2019/7/30 v1.0 + +*This document describes the current plan and vision for the Tangerine Network platform. While we intend to attempt to realize this vision, please recognize that it is dependent on a number of factors and subject to a wide range of risks. We do not guarantee, represent or warrant any of the statements in this document, because they are based on our current beliefs, expectations and assumptions, about which there can be no assurance due to various anticipated and unanticipated events that may occur. Please know that we seek to achieve the vision laid out in our whitepaper and website, but that you cannot rely on any of it coming true. Blockchain, cryptocurrencies, other aspects of our technology and these markets are in their infancy and will be subject to many challenges, competition and a changing environment. + + +## Token Allocation +The total supply of TAN tokens is fixed at **200 million**. The genesis token supply is **50 million** TAN and the other **150 million** TAN will be minted as mining rewards after Tangerine mainnet launches. The token allocation is shown below: + +<p align="center"> + <img src="https://i.imgur.com/h4fw4Vd.png" width="500"> + <br></br> + <b> Figure 1. Token Allocation </b> +</p> + +* 75% for Miner’s Reward + + For rewarding miners that actively participate in network consensus and smart contract executions on Tangerine Network. + +* 25% for Genesis Supply + + The genesis supply allocation is mostly used as stakes for genesis block proposer nodes. There are no private placement or any kind of token sale for Tangerine Network. For detailed allocation, please read bellow. + + +## Mining Model +Nodes that actively participate in validating transactions will get TAN tokens as mining rewards based on Tangerine’s Proof of Participation Model. + +### Proof-of-Participation Model +* Validator Eligibility + +A node is eligible to join as a validator if its TAN token deposit reaches the threshold of 1 million TAN. The deposit can come from the node itself or from any other accounts that support the node. It takes 2 epochs (2 hours) for the deposit to become effective, and another 24 hours for deposit withdrawals to become effective. + +* Symmetric Validator Power + +The validating power and the probability to be selected as a block producer among all validators are both fair and symmetric, meaning that the expected mining rewards of each validator will be the same as well. + +* Mining Rewards + +A validator earns transaction processing fees, gas fees, and mining rewards when it actively produces blocks and acks to other blocks. + + +## Adaptive Mining Mechanism +Tangerine adopts a novel adaptive mining mechanism that can self-adjust the token minting velocity. The token minting velocity is proportional to the participation rate of mining. If the demand of TAN token is strong, it will attract more token holders to participate in mining for rewards, hence the minting velocity will increase, and vice versa. This will make sure the system can keep demand and supply balanced by itself. + + +The formula of minting velocity is stated below: +<p align="center"> + <img src="https://i.imgur.com/zkco21K.png" width="400"> +</p> +r is total supply growth rate (the annual growth rate of total supply), vis node mining velocity (the annual mining rate of each node), and is mining participation rate (the percentage of deposited tokens in validators relative to current total token circulation). +Initially, v is 18% and will alter based on the total minted tokens under a half-life condition. +The relation between node mining velocity and minted tokens is shown below: + +* v= 18% when mainnet launches. + +* v= 9% after 75 million TAN tokens are minted. + +* v= 4.5% after another 37.5 million TAN tokens are minted, and so on. + +As an example, inniitialy each node can mine 1M * 18% = 180K TAN tokens per year. As total minted tokens hit 75M TAN, the annual mining rate per node will decrease from 18% to 9%, and as total minted tokens hit 125M TAN, the annual per node mining rate will decrease further from 9% to 4.5%, and so on. + +<p align="center"> + <img src="https://i.imgur.com/tpzzyjV.png" width="600"> + <br></br> + <b> Figure 2. Node Mining Velocity Half-Life Threshold </b> +</p> + + +## Mining Rewards in Circulation +Now, let’s consider the influence of mining participation rate. For example, the genesis supply of TAN token is 50M, if 25M tokens are deposited in validating nodes, the mining participation rate will be 50%. So the total supply growth rate will be 18% * 50% = 9%. +The total mining rewards in circulation based on different participation rates (30%, 60%) is shown in the figure below: +<p align="center"> + <img src="https://i.imgur.com/x3Tdj2p.png" width="600"> + <br></br> + <b> Figure 3. Total Mining Rewards in Circulation </b> +</p> + +Assuming the mining participation rate is fixed at 60%, r(total supply growth rate) per year is shown below: +<p align="center"> + <img src="https://i.imgur.com/HAhuKYm.png" width="600"> + <br></br> + <b> Figure 4. Total Mining Rewards in Circulation </b> +</p> + + +## Genesis Allocation +As stated above, the genesis supply is 50 million TAN and the allocation is shown below: +<p align="center"> + <img src="https://i.imgur.com/hkoOHeR.png" width="600"> + <br></br> + <b> Figure 5. Genesis Supply Allocation </b> +</p> + + +* 60% to genesis block proposers. The genesis block proposers consists of blockchain companies and universities mainly in Taiwan and Singapore. The maximum nodes the genesis supply can stakeis (50M * 60%) / 1M = 30 nodes. +* 20% to tech development. This allocation is mainly used to pay as salaries to the developers and bug bounties. +* 10% to marketing and promotion of Tangerine Network. +* 5% to the Tangerine Foundation for misc. operations. +* 5% for listing on top 5 exchanges in the world. + +## DISCLAIMER +**PLEASE READ THIS DISCLAIMER SECTION CAREFULLY. CONSULT LEGAL AND FINANCIAL EXPERTS FOR FURTHER GUIDANCE.** +The following information may be incomplete and in no way implies a contractual relationship. While we make every effort to ensure that all information in this Whitepaper is accurate and up to date, such material in no way constitutes professional advice. Tangerine Foundation neither guarantees nor accepts responsibility for the accuracy, reliability, or completeness of this content. The content may be subject to change at any time without prior notice. Individuals intending to purchase platform token should seek independent professional advice prior to acting on any of the information contained in this paper. + +**Disclaimer – TAN Tokens and Tangerine Foundation** + +1. Not Securities. +Use and purchase of the TAN Tokens carries significant financial risk. Tangerine Foundation hereby expressly disclaims that the transactions taking place on its platform pertain in any way to an offering of securities in any jurisdiction or that any documents published on its platform are solicitations for investment. + +2. Security of Platform. +You acknowledge that information you store or transfer through Tangerine Foundation may become irretrievably lost or corrupted or temporarily unavailable due to a variety of causes, including software failures, protocol changes by third party providers, internet outages, force majeure event or other disasters including third party DDOS attacks, scheduled or unscheduled maintenance, or other causes either within or outside Tangerine Foundation’s control. You are solely responsible for backing up and maintaining duplicate copies of any information you store or transfer through Tangerine Foundation’ services + +3. No Responsibilities for TAN Tokens +Use and purchase of the TAN Tokens carries significant financial risk. Tangerine Foundation does not provide token purchase, financial, or legal advice. The documents provided to you cannot substitute for professional advice and independent factual verification. You warrant that you have conducted your own research and analysis, independently verify any information upon which you wish to rely, consider your own personal circumstances and goals, and obtain independent financial advice from appropriate professionals before making any token purchase decision or taking any other action including without limitation purchasing any TAN Tokens. You further acknowledge and agree that Tangerine Foundation has no obligation of due diligence or fiduciary duty toward you. + +4. No Liability. +Neither Tangerine Foundation nor any person or entity associated with it, including but not limited to its agents, servants, employees, insurers, attorneys, successors, and assigns, will be liable, whether in contract, tort (including negligence), or otherwise, for any damage, expense, or other loss you may suffer arising out of any use of the TAN Tokens. + +5. Technology - Sophistication. +Tokens are often described in exceedingly technical language; a comprehensive understanding of applied cryptography and computer science is required in order to appreciate inherent risks. You represent and warrant that you have sufficient knowledge, market sophistication, experience, and/or professional advice sufficient to undertake a prudent evaluation of the merits and risks of purchasing the TAN Tokens. You agree to bear sole responsibility for the aforementioned purchase. + +6. Technology - No guarantee. +Neither Tangerine Foundation nor its affiliates owns or controls any of the underlying software through which blockchain networks are formed. Neither Tangerine Foundation nor its affiliates makes any guarantee of functionality, security, or availability of such software and networks. + +7. Technology - Forks. +The blockchain technology underlying tokens is subject to change at any time, including changes in operating rules (commonly referred to as “forks”), and blockchain networks may go offline as a result of bugs, hard forks, or a number of other unforeseeable reasons. Such changes may materially and adversely affect the value or function of the TAN Tokens. You agree that you are fully responsible for monitoring such changes and agree to bear all risks arising therefrom or relating thereto. + +8. Technology - Malicious Nodes. +Some nodes in the Tangerine Foundation network may be malicious and attempt to get rewarded without corresponding contribution; also, attackers may try to ruin the Tangerine Foundation ecosystem if they only suffer from minimal penalties. We need strong guarantees to protect the network from malicious attacks to ensure that the transactions are secured and the ecosystem is sustainable. Some attacks that could threaten a blockchain network are listed and discussed as follows: +Sybil Attack +Malicious nodes could create multiple Sybil identities to strive for more rewards or cheat the network. In general, the proof mechanism should have established barriers to prevent Sybil attacks; however, there is no guarantee such barriers will always be successful. +Out-of- Work Attack +While an attacker can control a lot of nodes, the nodes could be used to make some troubles on a distributed computing network. The nodes controlled by malicious attackers could be called zombies. An attack methodology is to ask the zombie nodes to quit or go on a strike at one time. On Tangerine Foundation network, the zombie nodes may take AI jobs but fail to complete them or return invalid results. If an AI job is assigned to a group of which most are zombie nodes, the AI job would receive unauthentic results or just simply fail. +Outsourcing Attack +Malicious nodes may outsource their jobs to other nodes, such that they may earn the rewards easily without consuming the corresponding computing power. On Tangerine Foundation network, nodes should present their capabilities to strive for taking jobs. Validation of node capabilities based on Proof-of-Intelligence may mitigate the behavior of outsourcing attack because the malicious nodes would lose their jobs if they do not endeavor to execute the same; however, there is no guarantee this approach will always be successful. +Cyber-attacks +In the event of a cyberattack on the TAN Tokens or the Tangerine Foundation, the TAN Tokens may be adversely affected. Neither Tangerine Foundation nor its affiliates makes any guarantee that it may foresee, prevent, mitigate, or take corrective action in the event of such attack. + +9. Regulatory Measures +Crypto-tokens are being, or may be overseen by the regulatory authorities of various jurisdictions. Tangerine Foundation may receive queries, notices, warnings, requests, or rulings from one or more regulatory authorities from time to time or may even be ordered to suspend or discontinue any action in connection with the TAN Tokens. The development of the TAN Tokens may be seriously affected, hindered, or terminated as a result. + +10. Illiquidity and Price Volatility +There may not be a demand for TAN Tokens. Tangerine Foundation is not responsible for the circulation and trading of TAN Tokens on the market. Tokens, if traded on markets, usually have extremely volatile prices. Fluctuations in price over short periods of time frequently occur, which price may be denominated in Bitcoin, Ether, US Dollars or any other fiat currency. Such fluctuations could result from market forces (including speculations), regulatory changes, technical innovations, availability of exchanges, and other objective factors and represent changes in the balance of supply and demand. +Tangerine Foundation does not make any representation or warranty, explicit or implicit, as to the usability or the value of the TAN Tokens. You understand and accept that there is no warranty or assurance that you will receive any benefits through the TAN Tokens. + +11. Compliance by Users. +You acknowledge and agree that Tangerine Foundation is not responsible for determining whether or which laws, rules, or regulations apply or may apply to your transactions (including, without limitation, any anti-money laundering laws, securities laws and tax laws). You acknowledge and agree that you are in compliance with all such laws, rules, or regulations as may be applicable to your transactions. Without limiting the foregoing, you acknowledge and agree that you are solely responsible for all tax obligations arising from your purchase of the TAN Tokens. You further acknowledge and agree that Tangerine Foundation shall not be liable, whether directly or indirectly, for any of your tax obligations. +Applicable law, regulation, and executive orders may require Tangerine Foundation to, upon request by government agencies, disclose information regarding your account(s). In the event such disclosure is compelled, you agree that Tangerine Foundation may disclose information regarding your accounts. While Tangerine Foundation will endeavor to, where commercially reasonable, give you prior notice of such disclosure, Tangerine Foundation makes no guarantees that such prior notice will be made. diff --git a/docs/DKG-TSIG-Protocol.md b/docs/DKG-TSIG-Protocol.md new file mode 100644 index 0000000..bfd28e8 --- /dev/null +++ b/docs/DKG-TSIG-Protocol.md @@ -0,0 +1,101 @@ +Tangerine DKG-TSIG Protocol +=========================== +### Parameter +* λ = MAX(One gossip duraion, transaction confirm latency) +* Signature = [BLS](https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham) +* Curve = BLS12_381 +* n = size of `notary_set` +* t = <img src="https://latex.codecogs.com/svg.latex?\inline%20\left\lfloor\frac{2n}{3}\right\rfloor%2B1" /> + +### Notes +* Complaints and nack complaints are stored in governance contract; therefore, the broadcast is reliable. +* Governance contract will do the sanity check for complaints and nack complaints before adding to its state. +* Once a validator proposed `DKGFinal_i`, it can no longer propose any complaint. +* After DKG finished, if successful qualify nodes size is less than <img src="https://latex.codecogs.com/svg.latex?\inline%20\left\lfloor\frac{5}{6}\right\rfloor" /> of notary set size, DKG will be rerun with different set of nodes. + +Phase 1 ID Registration +------- +### @ T < 0 + +Each validator registers its ID(`DKGMasterPublicKey_i`) with stake. + +**After λ** + +Each validator `i` broadcasts a `DKGMasterPublicKeyReady_i` message. + +Validator waits until seeing more than `2t+1` `DKGGroupPublicKeyReady` message than proceeds to Phase 2. + +Phase 2 Secret Key Share Exchange +------- +### @ T = 0 +Each validator `i` generates `n` (`n` = # of ID registered in phase 1) secret key shares (`SK_i,0, SK_i,1, ..., SK_i,n`) of order `t` and the secret key share is sent to the corresponding validator (`SK_i,j` is sent to validator `j`) via a secure channel. + +Each validator `i` broadcasts the master public key (`MPK_i = {MPK_i,0, MPK_i,1, ..., MPK_i,t}`) of order `t` associated with the secret key shares. + +Phase 3 Complaint +------- +### @ T = (0, λ) +Each validator `i` calculates public key shares (`PK_0,i, PK_1,i, ..., PK_n,i`) using corresponding master public key (`PK_j,i = F(MPK_j, i)`). + +Each validator `i` verifies if the secret key share `SK_j,i` is associated with the public key share of validator `j`, `PK_j,i`. If the verification fails, `i` broadcast complaint of `j`, `CMP_i,j`. + + +Phase 4 Nack Complaint +------- +### @ T = λ +If validator `i` did not receive `SK_j,i`, broadcast nack complaint of `j`, `NCMP_i,j`. + +Phase 5 Anti Nack Complaint +------- +### @ T = 2λ +If validator `j` sees `NCMP_i,j` for any `i`, broadcast secret key share `SK_j,i`. + +Phase 6 Rebroadcast Secret +------- +### @ T = 3λ +If validator `k` receive `SK_j,i` for the first time for `i` != `k`, broadcast it again. + +Phase 7 Enforce Complaint +------- +### @ T = 4λ +If validator `k` sees `SK_j,i` for `i` != `k`, verifies if the secret key share `SK_j,i` is associated with the public key share of validator `j`, `PK_j,i`. If the verification fails, `k` broadcast complaint of `j`, `CMP_k,j`. + +If validator `k` sees `NCMP_i,j` for `j` != `k` and did not receive `SK_j,i`, `k` broadcast nack complaint of `j`, `NCMP_k,j`. + + +Phase 8 DKG Finalize +------- +### @ T = 5λ +Each validator `i` broadcast a `DKGFinal_i` message. + + +Phase 9 Sign with CSK +------- +### @ T = 6λ + +Validator waits until seeing more than `2t+1` final message. + +If there are more than `t` nack complaints to validator `j` (<img src="https://latex.codecogs.com/svg.latex?\inline%20\sum_{i}%20NCMP_{i,j}%20>%20t" /> (`i` : for all validator `i`)), then `j` is marked as **Disqualified**. + +If there is **one** complaint, `CMP_i,j`, to validator `j`, then `j` is marked as **Disqualified**. + +Each validator `i` determines the combined secret key, <img src="https://latex.codecogs.com/svg.latex?\inline%20CSK_{i}%20=%20\sum_{k}%20SK_{k,i}" /> (`k`: validator `k` is not marked as **Disqualified**) + +If a validator `i` successfully recovered combined secret key, it will broadcast a `DKGSuccess_i` message. + +Each validator `i` sign the message with `CSK_i` and broadcast the partial signature, `PSign_i`. + +Each validator `i` determines the combined public key of validator `j`, <img src="https://latex.codecogs.com/svg.latex?\inline%20CPK_{j}%20=%20\sum_{k}%20PK_{k,j}" /> (`k`: validator `k` is not marked as **Disqualified**) + +Phase 10 TSIG +------- +### @ T = (6λ, +inf) +If validator `i` is not **Disqualified**, verify `PSign_i` with `CPK_i`. + +Collect more than `t` valid `PSign_i` and recover TSIG, `TSIG`. + +Phase 11 Verify TSIG +------- +Determines the group public key, <img src="https://latex.codecogs.com/svg.latex?\inline%20GPK%20=%20\sum_{k}%20MPK_{k,0}" /> (`k`: validator `k` is not marked as **Disqualified**) + +Verify `TSIG` with `GPK`.
\ No newline at end of file diff --git a/docs/DKGSet.md b/docs/DKGSet.md new file mode 100644 index 0000000..5f2fc94 --- /dev/null +++ b/docs/DKGSet.md @@ -0,0 +1,23 @@ +# DKGSet + +DKGSet will run several tasks during a round (or `epoch` described in Tangerine Consensus Algorithm). + +Suppose the interval `[0, T)` and `[T, 2T)` are round `r` and `r+1`, respectively. (`T` is the round interval defined in Governance Contract) + +The time `t` is the Consensus Timestamp of the delivered block. + +## @ t = T/2 +* DKGSet_r starts the TSIG protocol to generate `CRS_r+1 = TSIG(CRS_r)`. DKGSet_r+1 is then decided. +* After DKGSet_r+1 is decided, DKGSet_r+1 register their DKG ID. ([Phase 1 of DKG + TSIG Protocol](DKG-TSIG-Protocol.md#phase-1-id-registration)) + +## @ t = T * 2 / 3 +* DKGSet_r+1 starts the DKG protocol ([Phase 2 of DKG + TSIG Protocol](DKG-TSIG-Protocol.md#phase-2-secret-key-share-exchange)) + +## @ t = [T, 2T) +* DKGSet_r+1 calculate the `Block.Randomness = TSIG(Block.Hash)` using TSIG protocol for each block confirmed in the round `r+1`. ([On Chain Random Oracle](On-Chain-Random-Oracle.md)) + + +# Special Case for Round 0 +* `CRS_0` is defined in Genesis state. +* No DKGSet and `Block.Randomness`. +* `CRS_1` = `HASH(CRS_0)` diff --git a/docs/Dapp-Development-Guide.md b/docs/Dapp-Development-Guide.md new file mode 100644 index 0000000..75f354d --- /dev/null +++ b/docs/Dapp-Development-Guide.md @@ -0,0 +1,62 @@ +# DApp Development Guide + +> #### Migrate from Ethereum +> If you have already developed DApps on Ethereum, you can skip to [Migrate from Ethereum](Migrate-DApp-from-Ethereum.md) and learn what the differences between Tangerine and Ethereum are. + +## Introduction + +DApps are decentralized applications built on top of blockchain platforms like Tangerine or Ethereum. At the heart of every DApps are smart contracts. Smart contracts are programs compiled into VM bytecode and deployed onto the blockchain platform. + +After deployment, a smart contract resides on an address, just like any other regular account. Everyone in the system can interact with the smart contract by sending transactions to the contract address. + +Currently, Tangerine uses the same account system as Ethereum. Tangerine also has its default VM built from VM Ethereum's virtual machine (EVM). So DApp development on Tangerine is *almost* the same as on Ethereum. + +Some special functions are provided through precompiled contract, e.g on chain randomness. + +To use the on chain randomess feature, please see the read me of [Tangerine Network RNG Library](https://github.com/byzantine-lab/tangerine-random-lib) + +## Solidity + +The most commonly used language to develop a Tangerine/Ethereum DApp is Solidity, which we will introduce briefly in the [next section](Solidity.md). + +Tangerine's version of EVM is almost the same as the original EVM, therefore Tangerine version of Solidity is almost the same as the original Solidity. If you have built a smart contract on Ethereum, you can usually deploy the exact same contract onto Tangerine without any modification. + +However, there are still some minor differences between the Tangerine's version of Solidity and its Ethereum counterpart, because of the boost in performance and the [On-chain Random Oracle](On-Chain-Random-Oracle.md) that Tangerine provides. We will cover these differences in [Migrate from Ethereum](Migrate-from-Ethereum.md). + +## Remix IDE + +[Remix](https://remix.ethereum.org) is a web-based integrated development environment, built for Ethereum. + +With Remix IDE, you can develop, compile, deploy and debug your smart contracts easily from the same interface. + +## Truffle + +If you are developing apps with truffle, all you need to do as add the following network config into your truffle config: + +``` + networks: { + ... + "tangerine-mainnet": { + network_id: 373, + gasPrice: 24e9, + provider: function() { + return new HDWalletProvider(mnemonic, "https://mainnet-rpc.tangerine-network.io"); + }, + }, + "tangerine-testnet": { + network_id: 374, + gasPrice: 24e9, + provider: function() { + return new HDWalletProvider(mnemonic, "https://testnet-rpc.tangerine-network.io"); + }, + }, + } +``` + +## Interact With Smart Contracts + +Once you have deployed your smart contracts on chain, the next step is to interact with your contract from your UI, which can either be a web app or a native mobile app. [This section](Interact-with-Contracts.md) shows you how it's done. + +## Tools and Libraries + +Tangerine provides a wide range of tools and libraries for DApp development, listed [HERE](Tools-and-Libraries.md). diff --git a/docs/Exchange-Integration-Guide.md b/docs/Exchange-Integration-Guide.md new file mode 100644 index 0000000..b5c1049 --- /dev/null +++ b/docs/Exchange-Integration-Guide.md @@ -0,0 +1,33 @@ +# Exchange Integration Guide + +This guide provides all the necessary details for integrating Tangerine with your exchange. + +## Wallet +Tangerine TX signature algorithm is exactly the same as Ethereum (secp256k1), you can use existing Ethereum wallet with Tangerine. + +## RPC +Tangerine RPC is compatible with Ethereum. In theory, you can use existing Ethereum module with Tangerine by replacing the RPC endpoint: + +|Network|RESTful|WebSocket|Chain ID| +|---|---|---|---| +|Mainnet|https://mainnet-rpc.tangerine-network.io|wss://mainnet-rpc.tangerine-network.io/ws|373| +|Testnet|https://testnet-rpc.tangerine-network.io|wss://testnet-rpc.tangerine-network.io/ws|374| + +Since Tangerine produce around 1 block per second, it may incur a heavier load on your database infrastructure. Make sure you have enough DB instance to handle the load. + +## Starting a RPC Node + +Refer to [Running a RPC node](RPC-Node-Operation-Guide.md) for instructions to launch a RPC node by yourself. + +## Deposit Confirmation + +Tangerine consensus algorithm has explicit finality, meaning you only need to wait for **1 block confirmation** to credit the deposit. If you really want to make sure, you can wait for 2 confirmations to be sure. + +## Explorer + +Explorer link is as follows: + +|Network|Explorer| +|---|---| +|Mainnet|https://tangerine.garden| +|Testnet|https://testnet.tangerine.garden| diff --git a/docs/Explorer.md b/docs/Explorer.md new file mode 100644 index 0000000..5c16915 --- /dev/null +++ b/docs/Explorer.md @@ -0,0 +1,32 @@ +# Tangerine Garden + +Official blockchain explorer and web wallet for Tangerine. You can also check network status and interact with smart contracts in Tangerine Garden. + +## Usage + +Go directly to Tangerine Garden websites and start exploring Tangerine networks. +- [Mainnet](https://tangerine.garden) +- [Testnet](https://testnet.tangerine.garden) + +## Features + +#### View Network Status + +![](https://storage.googleapis.com/tangerine-network/wiki-assets/tangerine-garden.png) +Tangerine Garden provides a comprehensive chart and a series of stats for you to get a grasp of the current network status easily. + +#### View Governance Status + +You can check the network governance status on Tangerine Garden, including network configurations like block time, minimum staking amount, round length and currently active block producing nodes. + +#### View Blocks, Addresses and Transactions + +Just like every other blockchain explorers, you can check the details of blocks, addresses and transactions on Tangerine Garden. + +#### Wallet + +Tangerine Garden provides wallet UI, with connectability to Chrome/Firefox wallet extension, Ledger and TREZOR. You can manage your assets on Tangerine easily and securely with Tangerine Garden. + +#### Smart Contract Interactions + +Smart contract developers can verify their contract source code on Tangerine Garden. Once it's verified, users can see the contract source code and interact with it on Tangerine Garden UI. diff --git a/docs/Governance-Contract-Interface.md b/docs/Governance-Contract-Interface.md new file mode 100644 index 0000000..b3ed87e --- /dev/null +++ b/docs/Governance-Contract-Interface.md @@ -0,0 +1,1253 @@ +# Governance Contract Interface + +The Tangerine governance contract is implemented in Go, but it's ABI compatible with Solidity. + +The governance contract address is located at `0x246FcDE58581e2754f215A523C0718C4BFc8041F` + +The equivalent solidity interface can be found in the [byzantine-lab/governance-abi](https://github.com/byzantine-lab/governance-abi/blob/master/contracts/Governance.sol) repo. The governance contract ABI is as follows: + +<!-- DO NOT EDIT BELOW THIS LINE!! The below part is automatically generated from the governance-abi ci flow and any modification below will be lost. --> +<!-- [[ABI AUTOGEN START]] --> +``` +[ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "dkgSuccesses", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "notarySetSize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "nodes", + "outputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "publicKey", + "type": "bytes" + }, + { + "name": "staked", + "type": "uint256" + }, + { + "name": "fined", + "type": "uint256" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "location", + "type": "string" + }, + { + "name": "url", + "type": "string" + }, + { + "name": "unstaked", + "type": "uint256" + }, + { + "name": "unstakedAt", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "notaryParamBeta", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "miningVelocity", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lambdaBA", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minStake", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "crsRound", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "notaryParamAlpha", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "dkgSuccessesCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "dkgFinalizeds", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "blockGasLimit", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "dkgRound", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalStaked", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "nodesOffsetByAddress", + "outputs": [ + { + "name": "", + "type": "int256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "crs", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "roundLength", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nextHalvingSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "dkgComplaints", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "name": "dkgMasterPublicKeyOffset", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "dkgMPKReadys", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastHalvedAmount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "name": "finedRecords", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lambdaDKG", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "fineValues", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "roundHeight", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "dkgMPKReadysCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minBlockInterval", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "dkgMasterPublicKeys", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "lastProposedHeight", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minGasPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "dkgFinalizedsCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "name": "dkgComplaintsProposed", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "nodesOffsetByNodeKeyAddress", + "outputs": [ + { + "name": "", + "type": "int256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lockupPeriod", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "dkgResetCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [], + "name": "ConfigurationChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "Round", + "type": "uint256" + }, + { + "indexed": false, + "name": "CRS", + "type": "bytes32" + } + ], + "name": "CRSProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": true, + "name": "NewOwnerAddress", + "type": "address" + } + ], + "name": "NodeOwnershipTransfered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": false, + "name": "PublicKey", + "type": "bytes" + } + ], + "name": "NodePublicKeyReplaced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": false, + "name": "Amount", + "type": "uint256" + } + ], + "name": "Staked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": false, + "name": "Amount", + "type": "uint256" + } + ], + "name": "Unstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": false, + "name": "Amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + } + ], + "name": "NodeAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + } + ], + "name": "NodeRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": false, + "name": "Type", + "type": "uint256" + }, + { + "indexed": false, + "name": "Arg1", + "type": "bytes" + }, + { + "indexed": false, + "name": "Arg2", + "type": "bytes" + } + ], + "name": "Reported", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": false, + "name": "Amount", + "type": "uint256" + } + ], + "name": "Fined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "NodeAddress", + "type": "address" + }, + { + "indexed": false, + "name": "Amount", + "type": "uint256" + } + ], + "name": "FinePaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "Round", + "type": "uint256" + }, + { + "indexed": false, + "name": "BlockHeight", + "type": "uint256" + } + ], + "name": "DKGReset", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "name": "NewOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "MinStake", + "type": "uint256" + }, + { + "name": "LockupPeriod", + "type": "uint256" + }, + { + "name": "MinGasPrice", + "type": "uint256" + }, + { + "name": "BlockGasLimit", + "type": "uint256" + }, + { + "name": "LambdaBA", + "type": "uint256" + }, + { + "name": "LambdaDKG", + "type": "uint256" + }, + { + "name": "NotaryParamAlpha", + "type": "uint256" + }, + { + "name": "NotaryParamBeta", + "type": "uint256" + }, + { + "name": "RoundLength", + "type": "uint256" + }, + { + "name": "MinBlockInterval", + "type": "uint256" + }, + { + "name": "FineValues", + "type": "uint256[]" + } + ], + "name": "updateConfiguration", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "NewOwner", + "type": "address" + } + ], + "name": "transferNodeOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "OldOwner", + "type": "address" + }, + { + "name": "NewOwner", + "type": "address" + } + ], + "name": "transferNodeOwnershipByFoundation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "NewPublicKey", + "type": "bytes" + } + ], + "name": "replaceNodePublicKey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nodesLength", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "Round", + "type": "uint256" + }, + { + "name": "SignedCRS", + "type": "bytes" + } + ], + "name": "proposeCRS", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "Complaint", + "type": "bytes" + } + ], + "name": "addDKGComplaint", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "PublicKey", + "type": "bytes" + } + ], + "name": "addDKGMasterPublicKey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "MPKReady", + "type": "bytes" + } + ], + "name": "addDKGMPKReady", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "Finalize", + "type": "bytes" + } + ], + "name": "addDKGFinalize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "Success", + "type": "bytes" + } + ], + "name": "addDKGSuccess", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "PublicKey", + "type": "bytes" + }, + { + "name": "Name", + "type": "string" + }, + { + "name": "Email", + "type": "string" + }, + { + "name": "Location", + "type": "string" + }, + { + "name": "Url", + "type": "string" + } + ], + "name": "register", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "stake", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "Amount", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "withdrawable", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "NodeAddress", + "type": "address" + } + ], + "name": "payFine", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "Type", + "type": "uint256" + }, + { + "name": "Arg1", + "type": "bytes" + }, + { + "name": "Arg2", + "type": "bytes" + } + ], + "name": "report", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "NewSignedCRS", + "type": "bytes" + } + ], + "name": "resetDKG", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] +``` +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> +<!-- [[ABI AUTOGEN END]] --> diff --git a/docs/Governance-Contract.md b/docs/Governance-Contract.md new file mode 100644 index 0000000..c436d9f --- /dev/null +++ b/docs/Governance-Contract.md @@ -0,0 +1,74 @@ +## Content + +- [Contract Write Function](#contract-write-function) +- [Contract Read Function](#contract-read-function) + +## Contract Write function +In this section, we briefly introduce some functions that Tangerine governance provides to write in. + +### Register +1. In Tangerine wallet, switch to the `owner's account`. +2. Navigate to the `Write` tab of the governance contract and select `register` from the dropdown menu. +3. Fill in the information like below; currently, you need 1M TAN to run a BP node. + - Node Public Key (you must hold the corresponding secret key) + - Name of the node + - Contact email + - Node Location + - Website URL +4. Click `Send` and `confirm` in Tangerine wallet. + +### Pay Fine +1. In Tangerine wallet, switch to the account to pay the fine (it doesn't has to be the owner of that node) +2. Navigate to the `Write tab of the governance contract and select `payFine` from the dropdown menu. +3. Fill in the amount of fine to pay, and the address of that node. +4. Click `Send` and `confirm` in Tangerine wallet. + +> NOTE: Don't worry to over pay the fine, the transaction would succeed when the amount you pay matches the fine of that node. + +### Stake/Unstake +After registering, each node owner can continue depositing more stake into Tangerine governance contract. This is super easy to achieve in Tangerine governance contract. + 1. Switch to the `owner account` in Tangerine wallet. + 2. Navigate to the `Write` tab and select `stake` from the dropdown menu. + 3. Fill the amount of stake in the contract. + 4. Click `Send` and `confirm` in Tangerine wallet. + +On the other hand, each node owner can also unstake from Tangerine governance contract. This is almost identical to operating stake function. + 1. Switch to the `owner account` in Tangerine wallet. + 2. Navigate to the `Write` tab and select `unstake` from the dropdown menu. + 3. Fill the amount of unstake in the contract. + 4. Click `Send` and `confirm` in Tangerine wallet. + +To ensure the stability of Tangerine blockchain, the duration to withdraw the unstake coin is set 24 epochs, which corresponds around 1 day in real-world time. In the duration, the node can still propose block and earn the reward, but the node sill can be fined if violating any rule. +Note that, each node can only unstake once until the unstake is withdrawn. + +### Withdraw +After unstaking and wait for 24 epochs, the node can withdraw the stake. + 1. Switch to the `owner account` in Tangerine wallet. + 2. Navigate to the `Write` tab and select `withdraw` from the dropdown menu. + 3. Click `Send` and `confirm` in Tangerine wallet. + +### Transfer Node Owner +A node owner can also transfer the owner right to others. + 1. Switch to the `owner account` in Tangerine wallet. + 2. Navigate to the `Write` tab and select `TransferNodeOwnership` from the dropdown menu. + 3. Fill the `address` of the new owner. + 4. Click `Send` and `confirm` in Tangerine wallet. + +> WARNING: This is an IRREDUCIBLE operation. No one can recover if you transfer to a wrong address. Please double-check the address is correct. + +## Contract Read function +<!-- Most of the information can be found in Tangerine Garden website. To prevent in case, we introduce a method to read the status of Tangerine blockchain. --> + +The latest system parameters can be found in the governance contract. We introduce some fruquently used functions. + +### nodes +`nodes` returns the status of a node, where the input is the order of the node. The order of a node can be query by the function `nodesOffsetByAddress`. + +### nodeLength +`nodeLength` returns the current size of the node set. + +### nodesOffsetByAddress +`nodesOffsetByAddress` returns the order of a node, where the input is the address of the node. + +### minStake +`minStake` returns the minimum stake required to join the node set.
\ No newline at end of file diff --git a/docs/Hello-Tangerine.md b/docs/Hello-Tangerine.md new file mode 100644 index 0000000..1305c18 --- /dev/null +++ b/docs/Hello-Tangerine.md @@ -0,0 +1 @@ +# Hello Tangerine diff --git a/docs/Installing-Go.md b/docs/Installing-Go.md new file mode 100644 index 0000000..06582fd --- /dev/null +++ b/docs/Installing-Go.md @@ -0,0 +1,37 @@ +### Windows + +Download and run the installer found at http://golang.org/doc/install + +### OS X + +Download an install the darwin binary from https://golang.org/dl/ + +You can also install go using the Homebrew package manager. + +### Linux + +#### Ubuntu + +The Ubuntu repositories carry an old version of Go. + +Ubuntu users can use the 'gophers' PPA to install an up to date version of Go (version 1.10 or later is preferred). +See https://launchpad.net/~gophers/+archive/ubuntu/archive for more information. +Note that this PPA requires adding `/usr/lib/go-1.X/bin` to the executable PATH. + +#### Other distros + +Download the latest distribution + +`curl -O https://storage.googleapis.com/golang/go1.10.4.linux-amd64.tar.gz` + +Unpack it to the `/usr/local` (might require sudo) + +`tar -C /usr/local -xzf go1.10.4.linux-amd64.tar.gz` + +#### Set GOPATH and PATH + +For Go to work properly, you need to set the following two environment variables: + +- Setup a go folder `mkdir -p ~/go; echo "export GOPATH=$HOME/go" >> ~/.bashrc` +- Update your path `echo "export PATH=$PATH:$HOME/go/bin:/usr/local/go/bin" >> ~/.bashrc` +- Read the environment variables into current session: `source ~/.bashrc`
\ No newline at end of file diff --git a/docs/Interact-from-Mobile-App.md b/docs/Interact-from-Mobile-App.md new file mode 100644 index 0000000..6620ba5 --- /dev/null +++ b/docs/Interact-from-Mobile-App.md @@ -0,0 +1,3 @@ +# from Mobile App + +WIP diff --git a/docs/Interact-from-Web.md b/docs/Interact-from-Web.md new file mode 100644 index 0000000..66b6ee0 --- /dev/null +++ b/docs/Interact-from-Web.md @@ -0,0 +1,3 @@ +# from Web + +WIP diff --git a/docs/Interact-with-Contracts.md b/docs/Interact-with-Contracts.md new file mode 100644 index 0000000..352e1c9 --- /dev/null +++ b/docs/Interact-with-Contracts.md @@ -0,0 +1,3 @@ +# Interact with Contracts + +WIP diff --git a/docs/JSON-RPC-API.md b/docs/JSON-RPC-API.md new file mode 100644 index 0000000..0c025d5 --- /dev/null +++ b/docs/JSON-RPC-API.md @@ -0,0 +1,2381 @@ +# JSON-RPC API + +<!-- START doctoc generated TOC please keep comment here to allow auto update --> +<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> + +**Contents** + +- [JSON RPC API](#json-rpc-api) + - [JavaScript API](#javascript-api) + - [JSON-RPC Endpoint](#json-rpc-endpoint) + - [Go](#go) + - [JSON-RPC support](#json-rpc-support) + - [HEX value encoding](#hex-value-encoding) + - [The default block parameter](#the-default-block-parameter) + - [Curl Examples Explained](#curl-examples-explained) + - [JSON-RPC methods](#json-rpc-methods) + - [JSON RPC API Reference](#json-rpc-api-reference) + - [web3_clientVersion](#web3_clientversion) + - [Parameters](#parameters) + - [Returns](#returns) + - [Example](#example) + - [web3_sha3](#web3_sha3) + - [Parameters](#parameters-1) + - [Example Parameters](#example-parameters) + - [Returns](#returns-1) + - [Example](#example-1) + - [net_version](#net_version) + - [Parameters](#parameters-2) + - [Returns](#returns-2) + - [Example](#example-2) + - [net_listening](#net_listening) + - [Parameters](#parameters-3) + - [Returns](#returns-3) + - [Example](#example-3) + - [net_peerCount](#net_peercount) + - [Parameters](#parameters-4) + - [Returns](#returns-4) + - [Example](#example-4) + - [eth_protocolVersion](#eth_protocolversion) + - [Parameters](#parameters-5) + - [Returns](#returns-5) + - [Example](#example-5) + - [eth_syncing](#eth_syncing) + - [Parameters](#parameters-6) + - [Returns](#returns-6) + - [Example](#example-6) + - [eth_coinbase](#eth_coinbase) + - [Parameters](#parameters-7) + - [Returns](#returns-7) + - [Example](#example-7) + - [eth_gasPrice](#eth_gasprice) + - [Parameters](#parameters-8) + - [Returns](#returns-8) + - [Example](#example-8) + - [eth_accounts](#eth_accounts) + - [Parameters](#parameters-9) + - [Returns](#returns-9) + - [Example](#example-9) + - [eth_blockNumber](#eth_blocknumber) + - [Parameters](#parameters-10) + - [Returns](#returns-10) + - [Example](#example-10) + - [eth_getBalance](#eth_getbalance) + - [Parameters](#parameters-11) + - [Example Parameters](#example-parameters-1) + - [Returns](#returns-11) + - [Example](#example-11) + - [eth_getStorageAt](#eth_getstorageat) + - [Parameters](#parameters-12) + - [Returns](#returns-12) + - [Example](#example-12) + - [eth_getTransactionCount](#eth_gettransactioncount) + - [Parameters](#parameters-13) + - [Example Parameters](#example-parameters-2) + - [Returns](#returns-13) + - [Example](#example-13) + - [eth_getBlockTransactionCountByHash](#eth_getblocktransactioncountbyhash) + - [Parameters](#parameters-14) + - [Example Parameters](#example-parameters-3) + - [Returns](#returns-14) + - [Example](#example-14) + - [eth_getBlockTransactionCountByNumber](#eth_getblocktransactioncountbynumber) + - [Parameters](#parameters-15) + - [Example Parameters](#example-parameters-4) + - [Returns](#returns-15) + - [Example](#example-15) + - [eth_getCode](#eth_getcode) + - [Parameters](#parameters-16) + - [Example Parameters](#example-parameters-5) + - [Returns](#returns-16) + - [Example](#example-16) + - [eth_sign](#eth_sign) + - [Parameters](#parameters-17) + - [Returns](#returns-17) + - [Example](#example-17) + - [eth_sendTransaction](#eth_sendtransaction) + - [Parameters](#parameters-18) + - [Example Parameters](#example-parameters-6) + - [Returns](#returns-18) + - [Example](#example-18) + - [eth_sendRawTransaction](#eth_sendrawtransaction) + - [Parameters](#parameters-19) + - [Example Parameters](#example-parameters-7) + - [Returns](#returns-19) + - [Example](#example-19) + - [eth_call](#eth_call) + - [Parameters](#parameters-20) + - [Returns](#returns-20) + - [Example](#example-20) + - [eth_estimateGas](#eth_estimategas) + - [Parameters](#parameters-21) + - [Returns](#returns-21) + - [Example](#example-21) + - [eth_getBlockByHash](#eth_getblockbyhash) + - [Parameters](#parameters-22) + - [Example Parameters](#example-parameters-8) + - [Returns](#returns-22) + - [Example](#example-22) + - [eth_getBlockByNumber](#eth_getblockbynumber) + - [Parameters](#parameters-23) + - [Example Parameters](#example-parameters-9) + - [Returns](#returns-23) + - [Example](#example-23) + - [eth_getTransactionByHash](#eth_gettransactionbyhash) + - [Parameters](#parameters-24) + - [Example Parameters](#example-parameters-10) + - [Returns](#returns-24) + - [Example](#example-24) + - [eth_getTransactionByBlockHashAndIndex](#eth_gettransactionbyblockhashandindex) + - [Parameters](#parameters-25) + - [Example Parameters](#example-parameters-11) + - [Returns](#returns-25) + - [Example](#example-25) + - [eth_getTransactionByBlockNumberAndIndex](#eth_gettransactionbyblocknumberandindex) + - [Parameters](#parameters-26) + - [Example Parameters](#example-parameters-12) + - [Returns](#returns-26) + - [Example](#example-26) + - [eth_getTransactionReceipt](#eth_gettransactionreceipt) + - [Parameters](#parameters-27) + - [Example Parameters](#example-parameters-13) + - [Returns](#returns-27) + - [Example](#example-27) + - [eth_pendingTransactions](#eth_pendingtransactions) + - [Parameters](#parameters-28) + - [Example Parameters](#example-parameters-14) + - [Returns](#returns-28) + - [Example](#example-28) + - [eth_getUncleByBlockHashAndIndex](#eth_getunclebyblockhashandindex) + - [Parameters](#parameters-32) + - [Returns](#returns-32) + - [Example](#example-32) + - [eth_getUncleByBlockNumberAndIndex](#eth_getunclebyblocknumberandindex) + - [Parameters](#parameters-33) + - [Example Parameters](#example-parameters-15) + - [Returns](#returns-33) + - [Example](#example-33) + - [eth_newFilter](#eth_newfilter) + - [A note on specifying topic filters:](#a-note-on-specifying-topic-filters) + - [Parameters](#parameters-34) + - [Example Parameters](#example-parameters-16) + - [Returns](#returns-34) + - [Example](#example-34) + - [eth_newBlockFilter](#eth_newblockfilter) + - [Parameters](#parameters-35) + - [Returns](#returns-35) + - [Example](#example-35) + - [eth_newPendingTransactionFilter](#eth_newpendingtransactionfilter) + - [Parameters](#parameters-36) + - [Returns](#returns-36) + - [Example](#example-36) + - [eth_uninstallFilter](#eth_uninstallfilter) + - [Parameters](#parameters-37) + - [Example Parameters](#example-parameters-17) + - [Returns](#returns-37) + - [Example](#example-37) + - [eth_getFilterChanges](#eth_getfilterchanges) + - [Parameters](#parameters-38) + - [Example Parameters](#example-parameters-18) + - [Returns](#returns-38) + - [Example](#example-38) + - [eth_getFilterLogs](#eth_getfilterlogs) + - [Parameters](#parameters-39) + - [Example Parameters](#example-parameters-19) + - [Returns](#returns-39) + - [Example](#example-39) + - [eth_getLogs](#eth_getlogs) + - [Parameters](#parameters-40) + - [Example Parameters](#example-parameters-20) + - [Returns](#returns-40) + - [Example](#example-40) + - [eth_getWork](#eth_getwork) + - [Parameters](#parameters-41) + - [Returns](#returns-41) + - [Example](#example-41) + - [eth_submitWork](#eth_submitwork) + - [Parameters](#parameters-42) + - [Example Parameters](#example-parameters-21) + - [Returns](#returns-42) + - [Example](#example-42) + - [eth_submitHashrate](#eth_submithashrate) + - [Parameters](#parameters-43) + - [Example Parameters](#example-parameters-22) + - [Returns](#returns-43) + - [Example](#example-43) + - [db_putString](#db_putstring) + - [Parameters](#parameters-44) + - [Example Parameters](#example-parameters-23) + - [Returns](#returns-44) + - [Example](#example-44) + - [db_getString](#db_getstring) + - [Parameters](#parameters-45) + - [Example Parameters](#example-parameters-24) + - [Returns](#returns-45) + - [Example](#example-45) + - [db_putHex](#db_puthex) + - [Parameters](#parameters-46) + - [Example Parameters](#example-parameters-25) + - [Returns](#returns-46) + - [Example](#example-46) + - [db_getHex](#db_gethex) + - [Parameters](#parameters-47) + - [Example Parameters](#example-parameters-26) + - [Returns](#returns-47) + - [Example](#example-47) + - [shh_version](#shh_version) + - [Parameters](#parameters-48) + - [Returns](#returns-48) + - [Example](#example-48) + - [shh_post](#shh_post) + - [Parameters](#parameters-49) + - [Example Parameters](#example-parameters-27) + - [Returns](#returns-49) + - [Example](#example-49) + - [shh_newIdentity](#shh_newidentity) + - [Parameters](#parameters-50) + - [Returns](#returns-50) + - [Example](#example-50) + - [shh_hasIdentity](#shh_hasidentity) + - [Parameters](#parameters-51) + - [Example Parameters](#example-parameters-28) + - [Returns](#returns-51) + - [Example](#example-51) + - [shh_newGroup](#shh_newgroup) + - [Parameters](#parameters-52) + - [Returns](#returns-52) + - [Example](#example-52) + - [shh_addToGroup](#shh_addtogroup) + - [Parameters](#parameters-53) + - [Example Parameters](#example-parameters-29) + - [Returns](#returns-53) + - [Example](#example-53) + - [shh_newFilter](#shh_newfilter) + - [Parameters](#parameters-54) + - [Example Parameters](#example-parameters-30) + - [Returns](#returns-54) + - [Example](#example-54) + - [shh_uninstallFilter](#shh_uninstallfilter) + - [Parameters](#parameters-55) + - [Example Parameters](#example-parameters-31) + - [Returns](#returns-55) + - [Example](#example-55) + - [shh_getFilterChanges](#shh_getfilterchanges) + - [Parameters](#parameters-56) + - [Example Parameters](#example-parameters-32) + - [Returns](#returns-56) + - [Example](#example-56) + - [shh_getMessages](#shh_getmessages) + - [Parameters](#parameters-57) + - [Example Parameters](#example-parameters-33) + - [Returns](#returns-57) + - [Example](#example-57) + - [Extend JSON-RPC methods](#extend-json-rpc-methods) + - [Extend JSON RPC API Reference](#extend-json-rpc-api-reference) + - [eth_sendRawTransactions](#eth_sendRawTransactions) + - [Parameters](#parameters-58) + - [Returns](#returns-58) + - [Example](#example-58) + - [eth_getBlockReceiptsByHash](#eth_getBlockReceiptsByHash) + - [Parameters](#parameters-59) + - [Returns](#returns-59) + - [Example](#example-59) + +<!-- END doctoc generated TOC please keep comment here to allow auto update --> + +# JSON RPC API + +[JSON](http://json.org/) is a lightweight data-interchange format. It can represent numbers, strings, ordered sequences of values, and collections of name/value pairs. + +[JSON-RPC](http://www.jsonrpc.org/specification) is a stateless, light-weight remote procedure call (RPC) protocol. Primarily this specification defines several data structures and the rules around their processing. It is transport agnostic in that the concepts can be used within the same process, over sockets, over HTTP, or in many various message passing environments. It uses JSON ([RFC 4627](http://www.ietf.org/rfc/rfc4627.txt)) as data format. + +Geth 1.4 has experimental pub/sub support. See [this](https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB) page for more information. + +## JavaScript API + +To talk to a tangerine node from inside a JavaScript application use the [web3.js](https://github.com/ethereum/web3.js) library, which gives a convenient interface for the RPC methods. +See the [JavaScript API](https://github.com/ethereum/wiki/wiki/JavaScript-API) for more. +Extend API will support in the future. + +## JSON-RPC Endpoint + +Default JSON-RPC endpoints: + +| Client | URL | +|-------|:------------:| +| Go |http://localhost:8545 | + +### Go + +You can start the HTTP JSON-RPC with the `--rpc` flag +```bash +gtan --rpc +``` + +change the default port (8545) and listing address (localhost) with: + +```bash +gtan --rpc --rpcaddr <ip> --rpcport <portnumber> +``` + +If accessing the RPC from a browser, CORS will need to be enabled with the appropriate domain set. Otherwise, JavaScript calls are limit by the same-origin policy and requests will fail: + +```bash +gtan --rpc --rpccorsdomain "http://localhost:3000" +``` + +The JSON RPC can also be started from the [gtan console](https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console) using the `admin.startRPC(addr, port)` command. + +## HEX value encoding + +At present there are two key datatypes that are passed over JSON: unformatted byte arrays and quantities. Both are passed with a hex encoding, however with different requirements to formatting: + +When encoding **QUANTITIES** (integers, numbers): encode as hex, prefix with "0x", the most compact representation (slight exception: zero should be represented as "0x0"). Examples: +- 0x41 (65 in decimal) +- 0x400 (1024 in decimal) +- WRONG: 0x (should always have at least one digit - zero is "0x0") +- WRONG: 0x0400 (no leading zeroes allowed) +- WRONG: ff (must be prefixed 0x) + +When encoding **UNFORMATTED DATA** (byte arrays, account addresses, hashes, bytecode arrays): encode as hex, prefix with "0x", two hex digits per byte. Examples: +- 0x41 (size 1, "A") +- 0x004200 (size 3, "\0B\0") +- 0x (size 0, "") +- WRONG: 0xf0f0f (must be even number of digits) +- WRONG: 004200 (must be prefixed 0x) + +## The default block parameter + +The following methods have an extra default block parameter: + +- [eth_getBalance](#eth_getbalance) +- [eth_getCode](#eth_getcode) +- [eth_getTransactionCount](#eth_gettransactioncount) +- [eth_getStorageAt](#eth_getstorageat) +- [eth_call](#eth_call) + +When requests are made that act on the state o tangerine, the last default block parameter determines the height of the block. + +The following options are possible for the defaultBlock parameter: + +- `HEX String` - an integer block number +- `String "earliest"` for the earliest/genesis block +- `String "latest"` - for the latest mined block +- `String "pending"` - for the pending state/transactions + +## Curl Examples Explained + +The curl options below might return a response where the node complains about the content type, this is because the --data option sets the content type to application/x-www-form-urlencoded . If your node does complain, manually set the header by placing -H "Content-Type: application/json" at the start of the call. + +The examples also do not include the URL/IP & port combination which must be the last argument given to curl e.x. 127.0.0.1:8545 + +## JSON-RPC methods + +* [web3_clientVersion](#web3_clientversion) +* [web3_sha3](#web3_sha3) +* [net_version](#net_version) +* [net_peerCount](#net_peercount) +* [net_listening](#net_listening) +* [eth_protocolVersion](#eth_protocolversion) +* [eth_syncing](#eth_syncing) +* [eth_gasPrice](#eth_gasprice) +* [eth_accounts](#eth_accounts) +* [eth_blockNumber](#eth_blocknumber) +* [eth_getBalance](#eth_getbalance) +* [eth_getStorageAt](#eth_getstorageat) +* [eth_getTransactionCount](#eth_gettransactioncount) +* [eth_getBlockTransactionCountByHash](#eth_getblocktransactioncountbyhash) +* [eth_getBlockTransactionCountByNumber](#eth_getblocktransactioncountbynumber) +* [eth_getCode](#eth_getcode) +* [eth_sign](#eth_sign) +* [eth_sendTransaction](#eth_sendtransaction) +* [eth_sendRawTransaction](#eth_sendrawtransaction) +* [eth_call](#eth_call) +* [eth_estimateGas](#eth_estimategas) +* [eth_getBlockByHash](#eth_getblockbyhash) +* [eth_getBlockByNumber](#eth_getblockbynumber) +* [eth_getTransactionByHash](#eth_gettransactionbyhash) +* [eth_getTransactionByBlockHashAndIndex](#eth_gettransactionbyblockhashandindex) +* [eth_getTransactionByBlockNumberAndIndex](#eth_gettransactionbyblocknumberandindex) +* [eth_getTransactionReceipt](#eth_gettransactionreceipt) +* [eth_pendingTransactions](#eth_pendingtransactions) +* [eth_newFilter](#eth_newfilter) +* [eth_newBlockFilter](#eth_newblockfilter) +* [eth_newPendingTransactionFilter](#eth_newpendingtransactionfilter) +* [eth_uninstallFilter](#eth_uninstallfilter) +* [eth_getFilterChanges](#eth_getfilterchanges) +* [eth_getFilterLogs](#eth_getfilterlogs) +* [eth_getLogs](#eth_getlogs) +* [db_putString](#db_putstring) +* [db_getString](#db_getstring) +* [db_putHex](#db_puthex) +* [db_getHex](#db_gethex) +* [shh_post](#shh_post) +* [shh_version](#shh_version) +* [shh_newIdentity](#shh_newidentity) +* [shh_hasIdentity](#shh_hasidentity) +* [shh_newGroup](#shh_newgroup) +* [shh_addToGroup](#shh_addtogroup) +* [shh_newFilter](#shh_newfilter) +* [shh_uninstallFilter](#shh_uninstallfilter) +* [shh_getFilterChanges](#shh_getfilterchanges) +* [shh_getMessages](#shh_getmessages) + +## JSON RPC API Reference + +*** + +#### web3_clientVersion + +Returns the current client version. + +##### Parameters +none + +##### Returns + +`String` - The current client version. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' + +// Result +{ + "id":67, + "jsonrpc":"2.0", + "result": "Mist/v0.9.3/darwin/go1.4.1" +} +``` + +*** + +#### web3_sha3 + +Returns Keccak-256 (*not* the standardized SHA3-256) of the given data. + +##### Parameters + +1. `DATA` - the data to convert into a SHA3 hash. + +##### Example Parameters +```js +params: [ + "0x68656c6c6f20776f726c64" +] +``` + +##### Returns + +`DATA` - The SHA3 result of the given string. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":64}' + +// Result +{ + "id":64, + "jsonrpc": "2.0", + "result": "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad" +} +``` + +*** + +#### net_version + +Returns the current network id. + +##### Parameters +none + +##### Returns + +`String` - The current network id. +- `"373"`: Tangerine Network Mainnet +- `"374"`: Tangerine Network Testnet +- `"239"`: Taipei Testnet +- `"240"`: Yilan Testnet + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"net_version","params":[],"id":67}' + +// Result +{ + "id":67, + "jsonrpc": "2.0", + "result": "3" +} +``` + +*** + +#### net_listening + +Returns `true` if client is actively listening for network connections. + +##### Parameters +none + +##### Returns + +`Boolean` - `true` when listening, otherwise `false`. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"net_listening","params":[],"id":67}' + +// Result +{ + "id":67, + "jsonrpc":"2.0", + "result":true +} +``` + +*** + +#### net_peerCount + +Returns number of peers currently connected to the client. + +##### Parameters +none + +##### Returns + +`QUANTITY` - integer of the number of connected peers. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":74}' + +// Result +{ + "id":74, + "jsonrpc": "2.0", + "result": "0x2" // 2 +} +``` + +*** + +#### eth_protocolVersion + +Returns the curren tangerine protocol version. + +##### Parameters +none + +##### Returns + +`String` - The curren tangerine protocol version. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_protocolVersion","params":[],"id":67}' + +// Result +{ + "id":67, + "jsonrpc": "2.0", + "result": "0x40" +} +``` + +*** + +#### eth_syncing + +Returns an object with data about the sync status or `false`. + + +##### Parameters +none + +##### Returns + +`Object|Boolean`, An object with sync status data or `FALSE`, when not syncing: + - `startingBlock`: `QUANTITY` - The block at which the import started (will only be reset, after the sync reached his head) + - `currentBlock`: `QUANTITY` - The current block, same as eth_blockNumber + - `highestBlock`: `QUANTITY` - The estimated highest block + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": { + startingBlock: '0x384', + currentBlock: '0x386', + highestBlock: '0x454' + } +} +// Or when not syncing +{ + "id":1, + "jsonrpc": "2.0", + "result": false +} +``` +*** + +#### eth_gasPrice + +Returns the current price per gas in wei. + +##### Parameters +none + +##### Returns + +`QUANTITY` - integer of the current gas price in dal. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":73}' + +// Result +{ + "id":73, + "jsonrpc": "2.0", + "result": "0x09184e72a000" // 10000000000000 +} +``` + +*** + +#### eth_accounts + +Returns a list of addresses owned by client. + + +##### Parameters +none + +##### Returns + +`Array of DATA`, 20 Bytes - addresses owned by the client. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": ["0xc94770007dda54cF92009BFF0dE90c06F603a09f"] +} +``` + +*** + +#### eth_blockNumber + +Returns the number of most recent block. + +##### Parameters +none + +##### Returns + +`QUANTITY` - integer of the current block number the client is on. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' + +// Result +{ + "id":83, + "jsonrpc": "2.0", + "result": "0xc94" // 1207 +} +``` + +*** + +#### eth_getBalance + +Returns the balance of the account of given address. + +##### Parameters + +1. `DATA`, 20 Bytes - address to check for balance. +2. `QUANTITY|TAG` - integer block number, or the string `"latest"`, `"earliest"` or `"pending"`, see the [default block parameter](#the-default-block-parameter) + +##### Example Parameters +```js +params: [ + '0xc94770007dda54cF92009BFF0dE90c06F603a09f', + 'latest' +] +``` + +##### Returns + +`QUANTITY` - integer of the current balance in dal. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xc94770007dda54cF92009BFF0dE90c06F603a09f", "latest"],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x0234c8a3397aab58" // 158972490234375000 +} +``` + +*** + +#### eth_getStorageAt + +Returns the value from a storage position at a given address. + +##### Parameters + +1. `DATA`, 20 Bytes - address of the storage. +2. `QUANTITY` - integer of the position in the storage. +3. `QUANTITY|TAG` - integer block number, or the string `"latest"`, `"earliest"` or `"pending"`, see the [default block parameter](#the-default-block-parameter) + +##### Returns + +`DATA` - the value at this storage position. + +##### Example +Calculating the correct position depends on the storage to retrieve. Consider the following contract deployed at `0x295a70b2de5e3953354a6a8344e616ed314d7251` by address `0x391694e7e0b0cce554cb130d723a9d27458f9298`. + +``` +contract Storage { + uint pos0; + mapping(address => uint) pos1; + + function Storage() { + pos0 = 1234; + pos1[msg.sender] = 5678; + } +} +``` + +Retrieving the value of pos0 is straight forward: + +```js +curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"], "id": 1}' localhost:8545 + +{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000004d2"} +``` + +Retrieving an element of the map is harder. The position of an element in the map is calculated with: +```js +keccack(LeftPad32(key, 0), LeftPad32(map position, 0)) +``` + +This means to retrieve the storage on pos1["0x391694e7e0b0cce554cb130d723a9d27458f9298"] we need to calculate the position with: +```js +keccak(decodeHex("000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001")) +``` +The geth console which comes with the web3 library can be used to make the calculation: +```js +> var key = "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001" +undefined +> web3.sha3(key, {"encoding": "hex"}) +"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9" +``` +Now to fetch the storage: +```js +curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9", "latest"], "id": 1}' localhost:8545 + +{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000162e"} + +``` + +*** + +#### eth_getTransactionCount + +Returns the number of transactions *sent* from an address. + + +##### Parameters + +1. `DATA`, 20 Bytes - address. +2. `QUANTITY|TAG` - integer block number, or the string `"latest"`, `"earliest"` or `"pending"`, see the [default block parameter](#the-default-block-parameter) + +##### Example Parameters +```js +params: [ + '0xc94770007dda54cF92009BFF0dE90c06F603a09f', + 'latest' // state at the latest block +] +``` + +##### Returns + +`QUANTITY` - integer of the number of transactions send from this address. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xc94770007dda54cF92009BFF0dE90c06F603a09f","latest"],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +*** + +#### eth_getBlockTransactionCountByHash + +Returns the number of transactions in a block from a block matching the given block hash. + + +##### Parameters + +1. `DATA`, 32 Bytes - hash of a block. + +##### Example Parameters +```js +params: [ + '0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238' +] +``` + +##### Returns + +`QUANTITY` - integer of the number of transactions in this block. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByHash","params":["0xc94770007dda54cF92009BFF0dE90c06F603a09f"],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xc" // 11 +} +``` + +*** + +#### eth_getBlockTransactionCountByNumber +> > +Returns the number of transactions in a block matching the given block number. + + +##### Parameters + +1. `QUANTITY|TAG` - integer of a block number, or the string `"earliest"`, `"latest"` or `"pending"`, as in the [default block parameter](#the-default-block-parameter). + +##### Example Parameters +```js +params: [ + '0xe8', // 232 +] +``` + +##### Returns + +`QUANTITY` - integer of the number of transactions in this block. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByNumber","params":["0xe8"],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xa" // 10 +} +``` +*** + +#### eth_getCode + +Returns code at a given address. + + +##### Parameters + +1. `DATA`, 20 Bytes - address. +2. `QUANTITY|TAG` - integer block number, or the string `"latest"`, `"earliest"` or `"pending"`, see the [default block parameter](#the-default-block-parameter). + +##### Example Parameters +```js +params: [ + '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', + '0x2' // 2 +] +``` + +##### Returns + +`DATA` - the code from the given address. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getCode","params":["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x2"],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056" +} +``` + +*** + +#### eth_sign + +The sign method calculates an Tangerine specific signature with: `sign(keccak256("\x19Tangerine Signed Message:\n" + len(message) + message)))`. + +By adding a prefix to the message makes the calculated signature recognisable as an Tangerine specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. + +**Note** the address to sign with must be unlocked. + +##### Parameters +account, message + +1. `DATA`, 20 Bytes - address. +2. `DATA`, N Bytes - message to sign. + +##### Returns + +`DATA`: Signature + +##### Example + +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sign","params":["0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "0xdeadbeaf"],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" +} +``` + +*** + +#### eth_sendTransaction + +Creates new message call transaction or a contract creation, if the data field contains code. + +##### Parameters + +1. `Object` - The transaction object + - `from`: `DATA`, 20 Bytes - The address the transaction is send from. + - `to`: `DATA`, 20 Bytes - (optional when creating new contract) The address the transaction is directed to. + - `gas`: `QUANTITY` - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas. + - `gasPrice`: `QUANTITY` - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas + - `value`: `QUANTITY` - (optional) Integer of the value sent with this transaction + - `data`: `DATA` - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see [Solidity Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html) + - `nonce`: `QUANTITY` - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce. + +##### Example Parameters +```js +params: [{ + "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", // 30400 + "gasPrice": "0x9184e72a000", // 10000000000000 + "value": "0x9184e72a", // 2441406250 + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" +}] +``` + +##### Returns + +`DATA`, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available. + +Use [eth_getTransactionReceipt](#eth_gettransactionreceipt) to get the contract address, after the transaction was mined, when you created a contract. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{see above}],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} +``` + +*** + +#### eth_sendRawTransaction + +Creates new message call transaction or a contract creation for signed transactions. + +##### Parameters + +1. `DATA`, The signed transaction data. + +##### Example Parameters +```js +params: ["0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"] +``` + +##### Returns + +`DATA`, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available. + +Use [eth_getTransactionReceipt](#eth_gettransactionreceipt) to get the contract address, after the transaction was mined, when you created a contract. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":[{see above}],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} +``` + +*** + +#### eth_call + +Executes a new message call immediately without creating a transaction on the block chain. + + +##### Parameters + +1. `Object` - The transaction call object + - `from`: `DATA`, 20 Bytes - (optional) The address the transaction is sent from. + - `to`: `DATA`, 20 Bytes - The address the transaction is directed to. + - `gas`: `QUANTITY` - (optional) Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions. + - `gasPrice`: `QUANTITY` - (optional) Integer of the gasPrice used for each paid gas + - `value`: `QUANTITY` - (optional) Integer of the value sent with this transaction + - `data`: `DATA` - (optional) Hash of the method signature and encoded parameters. For details see [Ethereum Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) +2. `QUANTITY|TAG` - integer block number, or the string `"latest"`, `"earliest"` or `"pending"`, see the [default block parameter](#the-default-block-parameter) + +##### Returns + +`DATA` - the return value of executed contract. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{see above}],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x" +} +``` + +*** + +#### eth_estimateGas + +Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. The transaction will not be added to the blockchain. Note that the estimate may be significantly more than the amount of gas actually used by the transaction, for a variety of reasons including EVM mechanics and node performance. + +##### Parameters + +See [eth_call](#eth_call) parameters, expect that all properties are optional. If no gas limit is specified geth uses the block gas limit from the pending block as an upper bound. As a result the returned estimate might not be enough to executed the call/transaction when the amount of gas is higher than the pending block gas limit. + +##### Returns + +`QUANTITY` - the amount of gas used. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{see above}],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x5208" // 21000 +} +``` + +*** + +#### eth_getBlockByHash + +Returns information about a block by hash. + + +##### Parameters + +1. `DATA`, 32 Bytes - Hash of a block. +2. `Boolean` - If `true` it returns the full transaction objects, if `false` only the hashes of the transactions. + +##### Example Parameters +```js +params: [ + '0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331', + true +] +``` + +##### Returns + +`Object` - A block object, or `null` when no block was found: + + - `number`: `QUANTITY` - the block number. `null` when its pending block. + - `hash`: `DATA`, 32 Bytes - hash of the block. `null` when its pending block. + - `parentHash`: `DATA`, 32 Bytes - hash of the parent block. + - `nonce`: `DATA`, 8 Bytes - hash of the generated proof-of-work. `null` when its pending block. + - `sha3Uncles`: `DATA`, 32 Bytes - SHA3 of the uncles data in the block. + - `logsBloom`: `DATA`, 256 Bytes - the bloom filter for the logs of the block. `null` when its pending block. + - `transactionsRoot`: `DATA`, 32 Bytes - the root of the transaction trie of the block. + - `stateRoot`: `DATA`, 32 Bytes - the root of the final state trie of the block. + - `receiptsRoot`: `DATA`, 32 Bytes - the root of the receipts trie of the block. + - `miner`: `DATA`, 20 Bytes - the address of the beneficiary to whom the mining rewards were given. + - `difficulty`: `QUANTITY` - integer of the difficulty for this block. + - `totalDifficulty`: `QUANTITY` - integer of the total difficulty of the chain until this block. + - `extraData`: `DATA` - the "extra data" field of this block. + - `size`: `QUANTITY` - integer the size of this block in bytes. + - `gasLimit`: `QUANTITY` - the maximum gas allowed in this block. + - `gasUsed`: `QUANTITY` - the total used gas by all transactions in this block. + - `timestamp`: `QUANTITY` - the unix timestamp for when the block was collated. + - `transactions`: `Array` - Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. + - `uncles`: `Array` - Array of uncle hashes. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", true],"id":1}' + +// Result +{ +"id":1, +"jsonrpc":"2.0", +"result": { + "number": "0x1b4", // 436 + "hash": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5", + "nonce": "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", + "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a", + "difficulty": "0x027f07", // 163591 + "totalDifficulty": "0x027f07", // 163591 + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "size": "0x027f07", // 163591 + "gasLimit": "0x9f759", // 653145 + "gasUsed": "0x9f759", // 653145 + "timestamp": "0x54e34e8e" // 1424182926 + "transactions": [{...},{ ... }] + "uncles": ["0x1606e5...", "0xd5145a9..."] + } +} +``` + +*** + +#### eth_getBlockByNumber + +Returns information about a block by block number. + +##### Parameters + +1. `QUANTITY|TAG` - integer of a block number, or the string `"earliest"`, `"latest"` or `"pending"`, as in the [default block parameter](#the-default-block-parameter). +2. `Boolean` - If `true` it returns the full transaction objects, if `false` only the hashes of the transactions. + +##### Example Parameters +```js +params: [ + '0x1b4', // 436 + true +] +``` + +##### Returns + +See [eth_getBlockByHash](#eth_getblockbyhash) + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x1b4", true],"id":1}' +``` + +Result see [eth_getBlockByHash](#eth_getblockbyhash) + +*** + +#### eth_getTransactionByHash + +Returns the information about a transaction requested by transaction hash. + + +##### Parameters + +1. `DATA`, 32 Bytes - hash of a transaction + +##### Example Parameters +```js +params: [ + "0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b" +] +``` + +##### Returns + +`Object` - A transaction object, or `null` when no transaction was found: + + - `blockHash`: `DATA`, 32 Bytes - hash of the block where this transaction was in. `null` when its pending. + - `blockNumber`: `QUANTITY` - block number where this transaction was in. `null` when its pending. + - `from`: `DATA`, 20 Bytes - address of the sender. + - `gas`: `QUANTITY` - gas provided by the sender. + - `gasPrice`: `QUANTITY` - gas price provided by the sender in Wei. + - `hash`: `DATA`, 32 Bytes - hash of the transaction. + - `input`: `DATA` - the data send along with the transaction. + - `nonce`: `QUANTITY` - the number of transactions made by the sender prior to this one. + - `to`: `DATA`, 20 Bytes - address of the receiver. `null` when its a contract creation transaction. + - `transactionIndex`: `QUANTITY` - integer of the transaction's index position in the block. `null` when its pending. + - `value`: `QUANTITY` - value transferred in Wei. + - `v`: `QUANTITY` - ECDSA recovery id + - `r`: `DATA`, 32 Bytes - ECDSA signature r + - `s`: `DATA`, 32 Bytes - ECDSA signature s + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"],"id":1}' + +// Result +{ + "jsonrpc":"2.0", + "id":1, + "result":{ + "blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", + "blockNumber":"0x5daf3b", // 6139707 + "from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", + "gas":"0xc350", // 50000 + "gasPrice":"0x4a817c800", // 20000000000 + "hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", + "input":"0x68656c6c6f21", + "nonce":"0x15", // 21 + "to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", + "transactionIndex":"0x41", // 65 + "value":"0xf3dbb76162000", // 4290000000000000 + "v":"0x25", // 37 + "r":"0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", + "s":"0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c" + } +} +``` + +*** + +#### eth_getTransactionByBlockHashAndIndex + +Returns information about a transaction by block hash and transaction index position. + + +##### Parameters + +1. `DATA`, 32 Bytes - hash of a block. +2. `QUANTITY` - integer of the transaction index position. + +##### Example Parameters +```js +params: [ + '0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331', + '0x0' // 0 +] +``` + +##### Returns + +See [eth_getTransactionByHash](#eth_gettransactionbyhash) + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByBlockHashAndIndex","params":["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b", "0x0"],"id":1}' +``` + +Result see [eth_getTransactionByHash](#eth_gettransactionbyhash) + +*** + +#### eth_getTransactionByBlockNumberAndIndex + +Returns information about a transaction by block number and transaction index position. + + +##### Parameters + +1. `QUANTITY|TAG` - a block number, or the string `"earliest"`, `"latest"` or `"pending"`, as in the [default block parameter](#the-default-block-parameter). +2. `QUANTITY` - the transaction index position. + +##### Example Parameters +```js +params: [ + '0x29c', // 668 + '0x0' // 0 +] +``` + +##### Returns + +See [eth_getTransactionByHash](#eth_gettransactionbyhash) + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByBlockNumberAndIndex","params":["0x29c", "0x0"],"id":1}' +``` + +Result see [eth_getTransactionByHash](#eth_gettransactionbyhash) + +*** + +#### eth_getTransactionReceipt + +Returns the receipt of a transaction by transaction hash. + +**Note** That the receipt is not available for pending transactions. + + +##### Parameters + +1. `DATA`, 32 Bytes - hash of a transaction + +##### Example Parameters +```js +params: [ + '0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238' +] +``` + +##### Returns + +`Object` - A transaction receipt object, or `null` when no receipt was found: + + - `transactionHash `: `DATA`, 32 Bytes - hash of the transaction. + - `transactionIndex`: `QUANTITY` - integer of the transaction's index position in the block. + - `blockHash`: `DATA`, 32 Bytes - hash of the block where this transaction was in. + - `blockNumber`: `QUANTITY` - block number where this transaction was in. + - `from`: `DATA`, 20 Bytes - address of the sender. + - `to`: `DATA`, 20 Bytes - address of the receiver. null when it's a contract creation transaction. + - `cumulativeGasUsed `: `QUANTITY ` - The total amount of gas used when this transaction was executed in the block. + - `gasUsed `: `QUANTITY ` - The amount of gas used by this specific transaction alone. + - `contractAddress `: `DATA`, 20 Bytes - The contract address created, if the transaction was a contract creation, otherwise `null`. + - `logs`: `Array` - Array of log objects, which this transaction generated. + - `logsBloom`: `DATA`, 256 Bytes - Bloom filter for light clients to quickly retrieve related logs. + +It also returns _either_ : + + - `root` : `DATA` 32 bytes of post-transaction stateroot (pre Byzantium) + - `status`: `QUANTITY` either `1` (success) or `0` (failure) + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":1}' + +// Result +{ +"id":1, +"jsonrpc":"2.0", +"result": { + transactionHash: '0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238', + transactionIndex: '0x1', // 1 + blockNumber: '0xb', // 11 + blockHash: '0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b', + cumulativeGasUsed: '0x33bc', // 13244 + gasUsed: '0x4dc', // 1244 + contractAddress: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', // or null, if none was created + logs: [{ + // logs as returned by getFilterLogs, etc. + }, ...], + logsBloom: "0x00...0", // 256 byte bloom filter + status: '0x1' + } +} +``` + +*** + +#### eth_pendingTransactions + +Returns the pending transactions list. + +##### Parameters +none + +##### Returns + +`Array` - A list of pending transactions. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_pendingTransactions","params":[],"id":1}' + +// Result +{ +"id":1, +"jsonrpc":"2.0", +"result": [{ + blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + blockNumber: null, + from: '0x28bdb9c230f4d5e45435e4d006326ee32e46cb31', + gas: '0x204734', + gasPrice: '0x4a817c800', + hash: '0x8dfa6a59307a490d672494a171feee09db511f05e9c097e098edc2881f9ca4f6', + input: '0x6080604052600', + nonce: '0x12', + to: null, + transactionIndex: '0x0', + value: '0x0', + v: '0x3d', + r: '0xaabc9ddafffb2ae0bac4107697547d22d9383667d9e97f5409dd6881ce08f13f', + s: '0x69e43116be8f842dcd4a0b2f760043737a59534430b762317db21d9ac8c5034' + },....,{ + blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + blockNumber: null, + from: '0x28bdb9c230f4d5e45435e4d006326ee32e487b31', + gas: '0x205940', + gasPrice: '0x4a817c800', + hash: '0x8e4340ea3983d86e4b6c44249362f716ec9e09849ef9b6e3321140581d2e4dac', + input: '0xe4b6c4424936', + nonce: '0x14', + to: null, + transactionIndex: '0x0', + value: '0x0', + v: '0x3d', + r: '0x1ec191ef20b0e9628c4397665977cbe7a53a263c04f6f185132b77fa0fd5ca44', + s: '0x8a58e00c63e05cfeae4f1cf19f05ce82079dc4d5857e2cc281b7797d58b5faf' + }] +} +``` +*** + +#### eth_newFilter + +Creates a filter object, based on filter options, to notify when the state changes (logs). +To check if the state has changed, call [eth_getFilterChanges](#eth_getfilterchanges). + +##### A note on specifying topic filters: +Topics are order-dependent. A transaction with a log with topics [A, B] will be matched by the following topic filters: +* `[]` "anything" +* `[A]` "A in first position (and anything after)" +* `[null, B]` "anything in first position AND B in second position (and anything after)" +* `[A, B]` "A in first position AND B in second position (and anything after)" +* `[[A, B], [A, B]]` "(A OR B) in first position AND (A OR B) in second position (and anything after)" + +##### Parameters + +1. `Object` - The filter options: + - `fromBlock`: `QUANTITY|TAG` - (optional, default: `"latest"`) Integer block number, or `"latest"` for the last mined block or `"pending"`, `"earliest"` for not yet mined transactions. + - `toBlock`: `QUANTITY|TAG` - (optional, default: `"latest"`) Integer block number, or `"latest"` for the last mined block or `"pending"`, `"earliest"` for not yet mined transactions. + - `address`: `DATA|Array`, 20 Bytes - (optional) Contract address or a list of addresses from which logs should originate. + - `topics`: `Array of DATA`, - (optional) Array of 32 Bytes `DATA` topics. Topics are order-dependent. Each topic can also be an array of DATA with "or" options. + +##### Example Parameters +```js +params: [{ + "fromBlock": "0x1", + "toBlock": "0x2", + "address": "0x8888f1f195afa192cfee860698584c030f4c9db1", + "topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", null, ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]] +}] +``` + +##### Returns + +`QUANTITY` - A filter id. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"topics":["0x0000000000000000000000000000000000000000000000000000000012341234"]}],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +*** + +#### eth_newBlockFilter + +Creates a filter in the node, to notify when a new block arrives. +To check if the state has changed, call [eth_getFilterChanges](#eth_getfilterchanges). + +##### Parameters +None + +##### Returns + +`QUANTITY` - A filter id. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newBlockFilter","params":[],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +*** + +#### eth_newPendingTransactionFilter + +Creates a filter in the node, to notify when new pending transactions arrive. +To check if the state has changed, call [eth_getFilterChanges](#eth_getfilterchanges). + +##### Parameters +None + +##### Returns + +`QUANTITY` - A filter id. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newPendingTransactionFilter","params":[],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0x1" // 1 +} +``` + +*** + +#### eth_uninstallFilter + +Uninstalls a filter with given id. Should always be called when watch is no longer needed. +Additonally Filters timeout when they aren't requested with [eth_getFilterChanges](#eth_getfilterchanges) for a period of time. + + +##### Parameters + +1. `QUANTITY` - The filter id. + +##### Example Parameters +```js +params: [ + "0xb" // 11 +] +``` + +##### Returns + +`Boolean` - `true` if the filter was successfully uninstalled, otherwise `false`. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_uninstallFilter","params":["0xb"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": true +} +``` + +*** + +#### eth_getFilterChanges + +Polling method for a filter, which returns an array of logs which occurred since last poll. + + +##### Parameters + +1. `QUANTITY` - the filter id. + +##### Example Parameters +```js +params: [ + "0x16" // 22 +] +``` + +##### Returns + +`Array` - Array of log objects, or an empty array if nothing has changed since last poll. + +- For filters created with `eth_newBlockFilter` the return are block hashes (`DATA`, 32 Bytes), e.g. `["0x3454645634534..."]`. +- For filters created with `eth_newPendingTransactionFilter ` the return are transaction hashes (`DATA`, 32 Bytes), e.g. `["0x6345343454645..."]`. +- For filters created with `eth_newFilter` logs are objects with following params: + + - `removed`: `TAG` - `true` when the log was removed, due to a chain reorganization. `false` if its a valid log. + - `logIndex`: `QUANTITY` - integer of the log index position in the block. `null` when its pending log. + - `transactionIndex`: `QUANTITY` - integer of the transactions index position log was created from. `null` when its pending log. + - `transactionHash`: `DATA`, 32 Bytes - hash of the transactions this log was created from. `null` when its pending log. + - `blockHash`: `DATA`, 32 Bytes - hash of the block where this log was in. `null` when its pending. `null` when its pending log. + - `blockNumber`: `QUANTITY` - the block number where this log was in. `null` when its pending. `null` when its pending log. + - `address`: `DATA`, 20 Bytes - address from which this log originated. + - `data`: `DATA` - contains the non-indexed arguments of the log. + - `topics`: `Array of DATA` - Array of 0 to 4 32 Bytes `DATA` of indexed log arguments. (In *solidity*: The first topic is the *hash* of the signature of the event (e.g. `Deposit(address,bytes32,uint256)`), except you declared the event with the `anonymous` specifier.) + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x16"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": [{ + "logIndex": "0x1", // 1 + "blockNumber":"0x1b4", // 436 + "blockHash": "0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d", + "transactionHash": "0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf", + "transactionIndex": "0x0", // 0 + "address": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d", + "data":"0x0000000000000000000000000000000000000000000000000000000000000000", + "topics": ["0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5"] + },{ + ... + }] +} +``` + +*** + +#### eth_getFilterLogs + +Returns an array of all logs matching filter with given id. + + +##### Parameters + +1. `QUANTITY` - The filter id. + +##### Example Parameters +```js +params: [ + "0x16" // 22 +] +``` + +##### Returns + +See [eth_getFilterChanges](#eth_getfilterchanges) + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterLogs","params":["0x16"],"id":74}' +``` + +Result see [eth_getFilterChanges](#eth_getfilterchanges) + +*** + +#### eth_getLogs + +Returns an array of all logs matching a given filter object. + +##### Parameters + +1. `Object` - The filter options: + - `fromBlock`: `QUANTITY|TAG` - (optional, default: `"latest"`) Integer block number, or `"latest"` for the last mined block or `"pending"`, `"earliest"` for not yet mined transactions. + - `toBlock`: `QUANTITY|TAG` - (optional, default: `"latest"`) Integer block number, or `"latest"` for the last mined block or `"pending"`, `"earliest"` for not yet mined transactions. + - `address`: `DATA|Array`, 20 Bytes - (optional) Contract address or a list of addresses from which logs should originate. + - `topics`: `Array of DATA`, - (optional) Array of 32 Bytes `DATA` topics. Topics are order-dependent. Each topic can also be an array of DATA with "or" options. + - `blockhash`: `DATA`, 32 Bytes - (optional) With the addition of EIP-234 (Geth >= v1.8.13 or Parity >= v2.1.0), `blockHash` is a new filter option which restricts the logs returned to the single block with the 32-byte hash `blockHash`. Using `blockHash` is equivalent to `fromBlock` = `toBlock` = the block number with hash `blockHash`. If `blockHash` is present in the filter criteria, then neither `fromBlock` nor `toBlock` are allowed. + +##### Example Parameters +```js +params: [{ + "topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"] +}] +``` + +##### Returns + +See [eth_getFilterChanges](#eth_getfilterchanges) + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":74}' +``` + +Result see [eth_getFilterChanges](#eth_getfilterchanges) + +*** + +#### db_putString + +Stores a string in the local database. + +**Note** this function is deprecated and will be removed in the future. + +##### Parameters + +1. `String` - Database name. +2. `String` - Key name. +3. `String` - String to store. + +##### Example Parameters +```js +params: [ + "testDB", + "myKey", + "myString" +] +``` + +##### Returns + +`Boolean` - returns `true` if the value was stored, otherwise `false`. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"db_putString","params":["testDB","myKey","myString"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": true +} +``` + +*** + +#### db_getString + +Returns string from the local database. + +**Note** this function is deprecated and will be removed in the future. + +##### Parameters + +1. `String` - Database name. +2. `String` - Key name. + +##### Example Parameters +```js +params: [ + "testDB", + "myKey", +] +``` + +##### Returns + +`String` - The previously stored string. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"db_getString","params":["testDB","myKey"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": "myString" +} +``` + +*** + +#### db_putHex + +Stores binary data in the local database. + +**Note** this function is deprecated and will be removed in the future. + + +##### Parameters + +1. `String` - Database name. +2. `String` - Key name. +3. `DATA` - The data to store. + +##### Example Parameters +```js +params: [ + "testDB", + "myKey", + "0x68656c6c6f20776f726c64" +] +``` + +##### Returns + +`Boolean` - returns `true` if the value was stored, otherwise `false`. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"db_putHex","params":["testDB","myKey","0x68656c6c6f20776f726c64"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": true +} +``` + +*** + +#### db_getHex + +Returns binary data from the local database. + +**Note** this function is deprecated and will be removed in the future. + + +##### Parameters + +1. `String` - Database name. +2. `String` - Key name. + +##### Example Parameters +```js +params: [ + "testDB", + "myKey", +] +``` + +##### Returns + +`DATA` - The previously stored data. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"db_getHex","params":["testDB","myKey"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": "0x68656c6c6f20776f726c64" +} +``` + +*** + +#### shh_version + +Returns the current whisper protocol version. + +##### Parameters +none + +##### Returns + +`String` - The current whisper protocol version + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_version","params":[],"id":67}' + +// Result +{ + "id":67, + "jsonrpc": "2.0", + "result": "2" +} +``` + +*** + +#### shh_post + +Sends a whisper message. + +##### Parameters + +1. `Object` - The whisper post object: + - `from`: `DATA`, 60 Bytes - (optional) The identity of the sender. + - `to`: `DATA`, 60 Bytes - (optional) The identity of the receiver. When present whisper will encrypt the message so that only the receiver can decrypt it. + - `topics`: `Array of DATA` - Array of `DATA` topics, for the receiver to identify messages. + - `payload`: `DATA` - The payload of the message. + - `priority`: `QUANTITY` - The integer of the priority in a range from ... (?). + - `ttl`: `QUANTITY` - integer of the time to live in seconds. + +##### Example Parameters +```js +params: [{ + from: "0x04f96a5e25610293e42a73908e93ccc8c4d4dc0edcfa9fa872f50cb214e08ebf61a03e245533f97284d442460f2998cd41858798ddfd4d661997d3940272b717b1", + to: "0x3e245533f97284d442460f2998cd41858798ddf04f96a5e25610293e42a73908e93ccc8c4d4dc0edcfa9fa872f50cb214e08ebf61a0d4d661997d3940272b717b1", + topics: ["0x776869737065722d636861742d636c69656e74", "0x4d5a695276454c39425154466b61693532"], + payload: "0x7b2274797065223a226d6", + priority: "0x64", + ttl: "0x64", +}] +``` + +##### Returns + +`Boolean` - returns `true` if the message was send, otherwise `false`. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_post","params":[{"from":"0xc931d93e97ab07fe42d923478ba2465f2..","topics": ["0x68656c6c6f20776f726c64"],"payload":"0x68656c6c6f20776f726c64","ttl":0x64,"priority":0x64}],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": true +} +``` + +*** + +#### shh_newIdentity + +Creates new whisper identity in the client. + +##### Parameters +none + +##### Returns + +`DATA`, 60 Bytes - the address of the new identiy. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_newIdentity","params":[],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xc931d93e97ab07fe42d923478ba2465f283f440fd6cabea4dd7a2c807108f651b7135d1d6ca9007d5b68aa497e4619ac10aa3b27726e1863c1fd9b570d99bbaf" +} +``` + +*** + +#### shh_hasIdentity + +Checks if the client hold the private keys for a given identity. + + +##### Parameters + +1. `DATA`, 60 Bytes - The identity address to check. + +##### Example Parameters +```js +params: [ "0x04f96a5e25610293e42a73908e93ccc8c4d4dc0edcfa9fa872f50cb214e08ebf61a03e245533f97284d442460f2998cd41858798ddfd4d661997d3940272b717b1" +] +``` + +##### Returns + +`Boolean` - returns `true` if the client holds the privatekey for that identity, otherwise `false`. + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_hasIdentity","params":["0x04f96a5e25610293e42a73908e93ccc8c4d4dc0edcfa9fa872f50cb214e08ebf61a03e245533f97284d442460f2998cd41858798ddfd4d661997d3940272b717b1"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": true +} +``` + +*** + +#### shh_newGroup + +Creates a new group. + +##### Parameters +none + +##### Returns + +`DATA`, 60 Bytes - the address of the new group. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_newGroup","params":[],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xc65f283f440fd6cabea4dd7a2c807108f651b7135d1d6ca90931d93e97ab07fe42d923478ba2407d5b68aa497e4619ac10aa3b27726e1863c1fd9b570d99bbaf" +} +``` + +*** + +#### shh_addToGroup + +Adds a whisper identity to the group. + +##### Parameters + +1. `DATA`, 60 Bytes - The identity address to add to a group. + +##### Example Parameters +```js +params: [ "0x04f96a5e25610293e42a73908e93ccc8c4d4dc0edcfa9fa872f50cb214e08ebf61a03e245533f97284d442460f2998cd41858798ddfd4d661997d3940272b717b1" +] +``` + +##### Returns + +`Boolean` - returns `true` if the identity was successfully added to the group, otherwise `false`. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_addToGroup","params":["0x04f96a5e25610293e42a73908e93ccc8c4d4dc0edcfa9fa872f50cb214e08ebf61a03e245533f97284d442460f2998cd41858798ddfd4d661997d3940272b717b1"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": true +} +``` + +*** + +#### shh_newFilter + +Creates filter to notify, when client receives whisper message matching the filter options. + + +##### Parameters + +1. `Object` - The filter options: + - `to`: `DATA`, 60 Bytes - (optional) Identity of the receiver. *When present it will try to decrypt any incoming message if the client holds the private key to this identity.* + - `topics`: `Array of DATA` - Array of `DATA` topics which the incoming message's topics should match. You can use the following combinations: + - `[A, B] = A && B` + - `[A, [B, C]] = A && (B || C)` + - `[null, A, B] = ANYTHING && A && B` `null` works as a wildcard + +##### Example Parameters +```js +params: [{ + "topics": ['0x12341234bf4b564f'], + "to": "0x04f96a5e25610293e42a73908e93ccc8c4d4dc0edcfa9fa872f50cb214e08ebf61a03e245533f97284d442460f2998cd41858798ddfd4d661997d3940272b717b1" +}] +``` + +##### Returns + +`QUANTITY` - The newly created filter. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_newFilter","params":[{"topics": ['0x12341234bf4b564f'],"to": "0x2341234bf4b2341234bf4b564f..."}],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": "0x7" // 7 +} +``` + +*** + +#### shh_uninstallFilter + +Uninstalls a filter with given id. Should always be called when watch is no longer needed. +Additonally Filters timeout when they aren't requested with [shh_getFilterChanges](#shh_getfilterchanges) for a period of time. + + +##### Parameters + +1. `QUANTITY` - The filter id. + +##### Example Parameters +```js +params: [ + "0x7" // 7 +] +``` + +##### Returns + +`Boolean` - `true` if the filter was successfully uninstalled, otherwise `false`. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_uninstallFilter","params":["0x7"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": true +} +``` + +*** + +#### shh_getFilterChanges + +Polling method for whisper filters. Returns new messages since the last call of this method. + +**Note** calling the [shh_getMessages](#shh_getmessages) method, will reset the buffer for this method, so that you won't receive duplicate messages. + + +##### Parameters + +1. `QUANTITY` - The filter id. + +##### Example Parameters +```js +params: [ + "0x7" // 7 +] +``` + +##### Returns + +`Array` - Array of messages received since last poll: + + - `hash`: `DATA`, 32 Bytes (?) - The hash of the message. + - `from`: `DATA`, 60 Bytes - The sender of the message, if a sender was specified. + - `to`: `DATA`, 60 Bytes - The receiver of the message, if a receiver was specified. + - `expiry`: `QUANTITY` - Integer of the time in seconds when this message should expire (?). + - `ttl`: `QUANTITY` - Integer of the time the message should float in the system in seconds (?). + - `sent`: `QUANTITY` - Integer of the unix timestamp when the message was sent. + - `topics`: `Array of DATA` - Array of `DATA` topics the message contained. + - `payload`: `DATA` - The payload of the message. + - `workProved`: `QUANTITY` - Integer of the work this message required before it was send (?). + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_getFilterChanges","params":["0x7"],"id":73}' + +// Result +{ + "id":1, + "jsonrpc":"2.0", + "result": [{ + "hash": "0x33eb2da77bf3527e28f8bf493650b1879b08c4f2a362beae4ba2f71bafcd91f9", + "from": "0x3ec052fc33..", + "to": "0x87gdf76g8d7fgdfg...", + "expiry": "0x54caa50a", // 1422566666 + "sent": "0x54ca9ea2", // 1422565026 + "ttl": "0x64", // 100 + "topics": ["0x6578616d"], + "payload": "0x7b2274797065223a226d657373616765222c2263686...", + "workProved": "0x0" + }] +} +``` + +*** + +#### shh_getMessages + +Get all messages matching a filter. Unlike `shh_getFilterChanges` this returns all messages. + +##### Parameters + +1. `QUANTITY` - The filter id. + +##### Example Parameters +```js +params: [ + "0x7" // 7 +] +``` + +##### Returns + +See [shh_getFilterChanges](#shh_getfilterchanges) + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"shh_getMessages","params":["0x7"],"id":73}' +``` + +Result see [shh_getFilterChanges](#shh_getfilterchanges) + +## Extend JSON-RPC methods + +* [eth_sendRawTransactions](#eth_sendrawtransactions) +* [eth_getBlockReceiptsByHash](#eth_getblockreceiptsbyhash) + +## Extend JSON RPC API Reference + +#### eth_sendRawTransactions + +Batch creation with new message call transaction or a contract creation for signed transactions. + +##### Parameters + +1. `Array`, Array of signed transaction data. + +##### Example Parameters +```js +params: [[ +"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", +"0x8eb970870f0724456758bb8eb970870f072445675058bbe8dd67c5d32be8d46e8dd67c5d32d46be805", +]] +``` + +##### Returns + +`Array`, 32 Bytes - Array of available transaction hash. + +Use [eth_getTransactionReceipt](#eth_gettransactionreceipt) to get the contract address, after the transaction was mined, when you created a contract. + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransactions","params":[{see above}],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": ["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"] +} +``` + +*** + +#### eth_getBlockReceiptsByHash + +Returns all transaction receipts of a block by block hash. + +##### Parameters + +1. `DATA`, 32 Bytes - hash of a block + +##### Example Parameters +```js +params: [ + '0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331' +] +``` + +##### Returns + +`Array` - Array of transaction receipt object: + - `Object` + - `transactionHash `: `DATA`, 32 Bytes - hash of the transaction. + - `transactionIndex`: `QUANTITY` - integer of the transaction's index position in the block. + - `blockHash`: `DATA`, 32 Bytes - hash of the block where this transaction was in. + - `blockNumber`: `QUANTITY` - block number where this transaction was in. + - `from`: `DATA`, 20 Bytes - address of the sender. + - `to`: `DATA`, 20 Bytes - address of the receiver. null when it's a contract creation transaction. + - `cumulativeGasUsed `: `QUANTITY ` - The total amount of gas used when this transaction was executed in the block. + - `gasUsed `: `QUANTITY ` - The amount of gas used by this specific transaction alone. + - `contractAddress `: `DATA`, 20 Bytes - The contract address created, if the transaction was a contract creation, otherwise `null`. + - `logs`: `Array` - Array of log objects, which this transaction generated. + - `logsBloom`: `DATA`, 256 Bytes - Bloom filter for light clients to quickly retrieve related logs. + - It also returns _either_ : + - `root` : `DATA` 32 bytes of post-transaction stateroot (pre Byzantium) + - `status`: `QUANTITY` either `1` (success) or `0` (failure) + + +##### Example +```js +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":1}' + +// Result +{ +"id":1, +"jsonrpc":"2.0", +"result": [ + { + transactionHash: '0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238', + transactionIndex: '0x1', // 1 + blockNumber: '0xb', // 11 + blockHash: '0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b', + cumulativeGasUsed: '0x33bc', // 13244 + gasUsed: '0x4dc', // 1244 + contractAddress: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', // or null, if none was created + logs: [{ + // logs as returned by getFilterLogs, etc. + }, ...], + logsBloom: "0x00...0", // 256 byte bloom filter + status: '0x1' + }, + ] +} +``` + diff --git a/docs/List-of-Repositories.md b/docs/List-of-Repositories.md new file mode 100644 index 0000000..650853c --- /dev/null +++ b/docs/List-of-Repositories.md @@ -0,0 +1,6 @@ +# List of Repositories + +* [tangerine-consensus](https://github.com/byzantine-lab/tangerine-consensus): the consensus SDK and simulation. +* [go-tangerine](https://github.com/byzantine-lab/go-tangerine): the Tangerine fullnode implementation, based on go-ethereum. +* [governance-abi](https://github.com/byzantine-lab/governance-abi): the Tangerine governance contract interface solidity implementation for generating ABI. +* [TIPs](https://github.com/byzantine-lab/TIPs): a place for Tangerine Improvement Proposals diff --git a/docs/Migrate-from-Ethereum.md b/docs/Migrate-from-Ethereum.md new file mode 100644 index 0000000..03da247 --- /dev/null +++ b/docs/Migrate-from-Ethereum.md @@ -0,0 +1,42 @@ +# Migrate from Ethereum + +Tangerine's version of EVM is almost the same as the original EVM, therefore Tangerine version of Solidity is almost the same as the original Solidity. If you have built a smart contract on Ethereum, you can usually deploy the exact same contract onto Tangerine without any modification. + +However, there are still some minor differences between the Tangerine's version of Solidity and its Ethereum counterpart to look out for, as listed below: + +## Gas Limit + +In Tangerine, **there is no unspent gas**. + +If the actual execution of a transaction costs less gas than the set amount, **you still have to pay for the gas amount you've set**. So please set the gas amount wisely. + +The reason for this is that in Tangerine, transaction are not executed at the time they get packed into a block. So the number of transactions that can get into a block depends on the gas amount set in the transactions, not the actual gas amount consumed while executing the transactions. + +## On-Chain Random Oracle + +This is more of an additional feature than Ethereum's EVM. + +Tangerine provides [On-chain Random Oracle](On-Chain-Random-Oracle.md). This means you can get unbiased random seeds in your smart contract easily and at low cost. + +Here's a simple Solidity smart contract that utilizes Tangerine's on-chain randomness, +``` +pragma solidity ^0.5.2; + +import "github.com/byzantine-lab/tangerine-random-lib/RandomLib.sol"; + +contract Hello { + uint256 public value; + + event UpdateNumber(uint256 _value); + + function update() public { + value = Random.rand(); + emit UpdateNumber(value); + } + + function get() public view returns (uint256) { + return value; + } +} +``` +The `Random.rand()` function call used in the contract gives you the random seed generated from the threshold signature of a group of block producing nodes. diff --git a/docs/Node-Operator-Guide.md b/docs/Node-Operator-Guide.md new file mode 100644 index 0000000..ee2778b --- /dev/null +++ b/docs/Node-Operator-Guide.md @@ -0,0 +1 @@ +# Node Operator Guide diff --git a/docs/On-Chain-Random-Oracle.md b/docs/On-Chain-Random-Oracle.md new file mode 100644 index 0000000..269e404 --- /dev/null +++ b/docs/On-Chain-Random-Oracle.md @@ -0,0 +1,92 @@ +# On-Chain Random Oracle + +Most blockchains do not have a random source since they are not able to +generate an on-chain random number that can not be predicted beforehand. +Tangerine solves this problem by using threshold signature with BLS scheme. +Since this final threshold signature is only known after they are being +gathered together, one can not predict the signature before sending the +transaction that would be included in the given block. + +If you look at the block result using the RPC: +``` +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "dexconMeta": "...", + "extraData": "0x", + "gasLimit": "0x7a1200", + "gasUsed": "0x238f8", + "hash": "0x78ba157ae54a4784e1f0edbdac2b14e1f38f519d34d3d3164d75016ac90e8227", + "logsBloom": "...", + "miner": "0xb6a2e270b54f19b4002d6535a71cfdd1ca1f5fc1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x100", + "parentHash": "0x8da90bea16f9a6edf022030766950636caad7fbd0ef296e7d34da052d0fa4ca7", + "randomness": "0x895736dfafa3ce4e0f051fac7cc218cb092b67e88b7c25f4cf90e496e91c7d10e55a251e0ff6e655fdc8d866b85fe30c", + "receiptsRoot": "0xc627d0acef6f0592ffd775e05b4f6b36dce8065a217bf4c9fec0c538b8b46b7d", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x67b", + "stateRoot": "0xb728e453a70d2c6d5f9a00857aa697740c16770a696dd8a6594876c2b6f85a84", + "timestamp": "0x5bcf0935", + "totalDifficulty": "0x20100", + "transactions": [ + ... + ], + "transactionsRoot": "0x1b1e6b2a70de752b563fbeedb0461dca4af0c56e8dd3147b7a7ea3b2a701f6e6", + "uncles": [] + } +} +``` + +You can see there is a `randomness` field which standard Ethereum RPC does not +have. This `randomness` field is actually the threshold signature of the block +signed by the DKG set. + +Tangerine Network provides on-chain randomness through a precompiled contract. +Using a precompiled contract instead of introducing a new OP code ensures that +we are compatible with EVM, and eliminates the need to maintain a separate +toolchain. + +The precompiled contract is located at +`0xc327ff1025c5b3d2deb5e3f0f161b3f7e557579a`, which is the first 20 bytes of +`Keccak256Hash("Tangerine Network Random")`. The gas cost for each invocation is 64. + +To use the random library, simply include the library file then call `Random.rand()` to get the random number. + +## Example + +``` +import "github.com/byzantine-lab/tangerine-random-lib/RandomLib.sol"; + +contract UseRandom { + event Win(); + event Lose(); + + function readRand() public view returns (uint256) { + return Random.rand(); + } + + function bet() public { + if (Random.rand() % 100 > 50) { + emit Win(); + } else { + emit Lose(); + } + } +} +``` + + +The random variable is generated with the following formula: + +``` +rand = Keccak( Randomness . Caller . Nonce . RandCallIndex ) +``` + +* `Randomness` is the block randomness signed by DKG set, unique for each block. + * Note: `Randomness` field is not available in the initial round. +* `Caller` is the address of the contract caller. +* `Nonce` is the account nonce of the original caller. +* `RandCallIndex` number of times OP_RAND is called in the current transaction. diff --git a/docs/Papers.md b/docs/Papers.md new file mode 100644 index 0000000..589262d --- /dev/null +++ b/docs/Papers.md @@ -0,0 +1,36 @@ +# Tangerine papers + +## Fair Byzantine Agreements for Blockchains + +Author: Tzu-Wei Chao, Hao Chung, Po-Chun Kuo\ +(Submitted on 8 Jul 2019) + +<p align="center"> + <img src="https://i.imgur.com/MS0vZxT.png"> +</p> + + +Byzantine general problem is the core problem of the consensus algorithm, +and many protocols are proposed recently to improve the decentralization level, +the performance and the security of the blockchain. There are two challenging +issues when the blockchain is operating in practice. First, the outcomes of the +consensus algorithm are usually related to the incentive model, so whether each +participant's value has an equal probability of being chosen becomes essential. +However, the issues of fairness are not captured in the traditional security +definition of Byzantine agreement. Second, the blockchain should be resistant to +network failures, such as cloud services shut down or malicious attack, while +remains the high performance most of the time. \ +This paper has two main contributions. First, we propose a novel notion called +fair validity for Byzantine agreement. Intuitively, fair validity lower-bounds +the expected numbers that honest nodes' values being decided if the protocol is +executed many times. However, we also show that any Byzantine agreement could +not achieve fair validity in an asynchronous network, so we focus on synchronous +protocols. This leads to our second contribution: we propose a fair, responsive +and partition-resilient Byzantine agreement protocol tolerating up to 1/3 +corruptions. Fairness means that our protocol achieves fair validity. +Responsiveness means that the termination time only depends on the actual +network delay instead of depending on any pre-determined time bound. +Partition-resilience means that the safety still holds even if the network is +partitioned, and the termination will hold if the partition is resolved. + +[Paper Link](https://arxiv.org/abs/1907.03437)
\ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..256f50d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,29 @@ +# Getting Started + +Tangerine is a permissionless, proof-of-stake blockchain system that features high throughput and low latency. Current mainnnet is able to reach 10K TPS, and maintain ~ 1 second confirmation latency. + +This documentation shows your way around [Tangerine](https://tangerine-network.io), the next generation blockchain platform. + +## Overview + +#### Accessing Tangerine Network + +To create a Tangerine wallet and start using Tangerine blockchain platform, follow [wallet creation guide](Create-Wallet.md). + +#### DApp Development + +- To learn abour DApp (decentralized apps) development and build DApps on Tangerine, follow [DApp development guide](Dapp-Development-Guide.md). +- If you have already developed DApps on Ethereum and is planning to move your existing DApp onto Tangerine, check out [Etherum DApp migration guide](Migrate-from-Ethereum.md). + +#### Node Operation + +- To run a BP (block producing) full-node, follow [BP node operation guide](BP-Node-Operation-Guide.md). +- If you simply need to communicate to Tangerine network, like sending transactions or looking up network state, follow [RPC node operation guide](RPC-Node-Operation-Guide.md). + +#### Fullnode Development + +You can contribute to the development of Tangerine itself! Get started with [Tangerine fullnode development guide](Fullnode-Development.md). + +#### Technical Documentations + +To learn more about how Tangerine works, check out our [technical documenations](Technical-Documentations.md) diff --git a/docs/RPC-Node-Operation-Guide.md b/docs/RPC-Node-Operation-Guide.md new file mode 100644 index 0000000..cca61dd --- /dev/null +++ b/docs/RPC-Node-Operation-Guide.md @@ -0,0 +1,88 @@ +# Running a RPC node + +## Content + +- [Overview](#overview) +- [System Requirement](#system-requirement) +- [Software Instruction](#software-instruction) + +## Overview + +A RPC node is the data access layer of blockchains. It usually won't join the mining process but only try to sync the latest confirmed state from other nodes. With those datum in hands, a RPC node can provide these functionalities: +- Pack and send transactions +- Allow other services (like **wallet** or **explorer**) to access states on blockchains in standard way, like **jsonrpc**. + +## System Requirement + +Refer to [System requirement](BP-Node-Operation-Guide.md#system-requirement) section in BP node operation guide. + +## Software Instruction + +Different from running a BP node, you don't have to +- create a node key +- register your node + +The command line to start a RPC node is different, too: +``` +docker run -v $PWD:/mnt -it byzantinelab/go-tangerine \ + --datadir=/mnt/datadir \ + --syncmode=fast \ + --rpc \ + --rpcapi=eth,net,web3 \ + --rpcaddr=0.0.0.0 \ + --rpcvhosts=* \ + --rpccorsdomain=* \ + --ws \ + --wsapi=eth,net,web3 \ + --wsaddr=0.0.0.0 \ + --wsorigins=* \ + --cache=1024 \ + --gcmode=archive \ + --metrics \ + --pprof \ + --pprofaddr=0.0.0.0 +``` +You should be able to see these logs, which simply means your RPC node tries to sync blocks from other peers and it would take a while. If not, make sure tcp/30303 and udp/30303 is not blocked by the firewall. +``` +... +INFO [04-18|12:23:33.783] Imported new state entries ... +INFO [04-18|12:23:35.647] Imported new state entries ... +INFO [04-18|12:23:37.714] Imported new block receipts ... +INFO [04-18|12:23:38.471] Imported new block receipts ... +... +``` +To make sure your RPC node is ready for usage, you can try to get the count of blocks it received via this command: +``` +curl -X POST \ + -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ + http://localhost:8545 +``` +You should be able to see something similar in return (**0xd482e** is the hex form of **870062**): +``` +{"jsonrpc":"2.0","id":1,"result":"0xd482e"} +``` + +### RPC Node for Testnet + +It simply to launch a RPC node for testnet by adding network flag `--testnet`: +``` +docker run -v $PWD:/mnt -it byzantinelab/go-tangerine \ + --testnet \ + --datadir=/mnt/datadir \ + --syncmode=fast \ + --rpc \ + --rpcapi=eth,net,web3 \ + --rpcaddr=0.0.0.0 \ + --rpcvhosts=* \ + --rpccorsdomain=* \ + --ws \ + --wsapi=eth,net,web3 \ + --wsaddr=0.0.0.0 \ + --wsorigins=* \ + --cache=1024 \ + --gcmode=archive \ + --metrics \ + --pprof \ + --pprofaddr=0.0.0.0 +``` diff --git a/docs/RPC-PUB-SUB.md b/docs/RPC-PUB-SUB.md new file mode 100644 index 0000000..2e3fda4 --- /dev/null +++ b/docs/RPC-PUB-SUB.md @@ -0,0 +1,142 @@ +# RPC PUB-SUB + +Tangerine fullnode supports pub/sub using subscriptions as defined in the JSON-RPC 2.0 specification. This allows clients to wait for events instead of polling for them. + +It works by subscribing to particular events. The node will return a subscription id. For each event that matches the subscription a notification with relevant data is send together with the subscription id. + +Example: + + // create subscription + >> {"id": 1, "method": "eth_subscribe", "params": ["newHeads", {}]} + << {"jsonrpc":"2.0","id":1,"result":"0xcd0c3e8af590364c09d0fa6a1210faf5"} + + // incoming notifications + << {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0xcd0c3e8af590364c09d0fa6a1210faf5","result":{"difficulty":"0xd9263f42a87",<...>, "uncles":[]}}} + << {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0xcd0c3e8af590364c09d0fa6a1210faf5","result":{"difficulty":"0xd90b1a7ad02", <...>, "uncles":["0x80aacd1ea4c9da32efd8c2cc9ab38f8f70578fcd46a1a4ed73f82f3e0957f936"]}}} + + // cancel subscription + >> {"id": 1, "method": "eth_unsubscribe", "params": ["0xcd0c3e8af590364c09d0fa6a1210faf5"]} + << {"jsonrpc":"2.0","id":1,"result":true} + +# Considerations +1. notifications are send for current events and not for past events. If your use case requires you not to miss any notifications than subscriptions are probably not the best option. +2. subscriptions require a full duplex connection. Geth offers such connections in the form of websockets (enable with --ws) and ipc (enabled by default). +3. subscriptions are coupled to a connection. If the connection is closed all subscriptions that are created over this connection are removed. +4. notifications are stored in an internal buffer and sent from this buffer to the client. If the client is unable to keep up and the number of buffered notifications reaches a limit (currently 10k) the connection is closed. Keep in mind that subscribing to some events can cause a flood of notifications, e.g. listening for all logs/blocks when the node starts to synchronize. + +## Create subscription +Subscriptions are creates with a regular RPC call with `eth_subscribe` as method and the subscription name as first parameter. If successful it returns the subscription id. + +### Parameters +1. subscription name +2. optional arguments + +### Example + + >> {"id": 1, "method": "eth_subscribe", "params": ["newHeads", {"includeTransactions": true}]} + << {"id": 1, "jsonrpc": "2.0", "result": "0x9cef478923ff08bf67fde6c64013158d"} + +## Cancel subscription +Subscriptions are cancelled with a regular RPC call with `eth_unsubscribe` as method and the subscription id as first parameter. It returns a bool indicating if the subscription was cancelled successful. + +### Parameters +1. subscription id + +### Example + + >> {"id": 1, "method": "eth_unsubscribe", "params": ["0x9cef478923ff08bf67fde6c64013158d"]} + << {"jsonrpc":"2.0","id":1,"result":true} + +# Supported subscriptions + +## newHeads +Fires a notification each time a new header is appended to the chain, including chain reorganizations. Users can use the bloom filter to determine if the block contains logs that are interested to them. + +In case of a chain reorganization the subscription will emit all new headers for the new chain. Therefore the subscription can emit multiple headers on the same height. + +### Example +``` + >> {"id": 1, "method": "eth_subscribe", "params": ["newHeads"]} + << {"jsonrpc":"2.0","id":2,"result":"0x9ce59a13059e417087c02d3236a0b1cc"} + + << { + "jsonrpc": "2.0", + "method": "eth_subscription", + "params": { + "result": { + "difficulty": "0x15d9223a23aa", + "extraData": "0xd983010305844765746887676f312e342e328777696e646f7773", + "gasLimit": "0x47e7c4", + "gasUsed": "0x38658", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", + "nonce": "0x084149998194cc5f", + "number": "0x1348c9", + "parentHash": "0x7736fab79e05dc611604d22470dadad26f56fe494421b5b333de816ce1f25701", + "receiptRoot": "0x2fab35823ad00c7bb388595cb46652fe7886e00660a01e867824d3dceb1c8d36", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xb3346685172db67de536d8765c43c31009d0eb3bd9c501c9be3229203f15f378", + "timestamp": "0x56ffeff8", + "transactionsRoot": "0x0167ffa60e3ebc0b080cdb95f7c0087dd6c0e61413140e39d94d3468d7c9689f" + }, + "subscription": "0x9ce59a13059e417087c02d3236a0b1cc" + } +} +``` + +## logs +Returns logs that are included in new imported blocks and match the given filter criteria. + +In case of a chain reorganization previous sent logs that are on the old chain will be resend with the `removed` property set to true. Logs from transactions that ended up in the new chain are emitted. Therefore a subscription can emit logs for the same transaction multiple times. + +### Parameters +1. `object` with the following (optional) fields + - **address**, either an address or an array of addresses. Only logs that are created from these addresses are returned (optional) + - **topics**, only logs which match the specified topics (optional) + + +### Example + >> {"id": 1, "method": "eth_subscribe", "params": ["logs", {"address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd", "topics": ["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]} + << {"jsonrpc":"2.0","id":2,"result":"0x4a8a4c0517381924f9838102c5a4dcb7"} + + << {"jsonrpc":"2.0","method":"eth_subscription","params": {"subscription":"0x4a8a4c0517381924f9838102c5a4dcb7","result":{"address":"0x8320fe7702b96808f7bbc0d4a888ed1468216cfd","blockHash":"0x61cdb2a09ab99abf791d474f20c2ea89bf8de2923a2d42bb49944c8c993cbf04","blockNumber":"0x29e87","data":"0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003","logIndex":"0x0","topics":["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"],"transactionHash":"0xe044554a0a55067caafd07f8020ab9f2af60bdfe337e395ecd84b4877a3d1ab4","transactionIndex":"0x0"}}} + +## newPendingTransactions +Returns the hash for all transactions that are added to the pending state and are signed with a key that is available in the node. + +When a transaction that was previously part of the canonical chain isn't part of the new canonical chain after a reogranization its again emitted. + +### Parameters +none + +### Example + >> {"id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]} + << {"jsonrpc":"2.0","id":2,"result":"0xc3b33aa549fb9a60e95d21862596617c"} + + << { + "jsonrpc":"2.0", + "method":"eth_subscription", + "params":{ + "subscription":"0xc3b33aa549fb9a60e95d21862596617c", + "result":"0xd6fdc5cc41a9959e922f30cb772a9aef46f4daea279307bc5f7024edc4ccd7fa" + } + } + +## syncing +Indicates when the node starts or stops synchronizing. The result can either be a boolean indicating that the synchronization has started (true), finished (false) or an object with various progress indicators. + +### Parameters +none + +### Example + >> {"id": 1, "method": "eth_subscribe", "params": ["syncing"]} + << {"jsonrpc":"2.0","id":2,"result":"0xe2ffeb2703bcf602d42922385829ce96"} + + << {"subscription":"0xe2ffeb2703bcf602d42922385829ce96","result":{"syncing":true,"status":{"startingBlock":674427,"currentBlock":67400,"highestBlock":674432,"pulledStates":0,"knownStates":0}}}} + + +## Possible future subscription: +- balance changes +- account changes +- nonce changes +- storage changes in contracts diff --git a/docs/Recovery-Mechanism.md b/docs/Recovery-Mechanism.md new file mode 100644 index 0000000..6a55fd6 --- /dev/null +++ b/docs/Recovery-Mechanism.md @@ -0,0 +1,5 @@ +# Recovery Mechanism + +Tangerine's automatic recovery mechanism will kick in in the catastrophic event that complete Tangerine Network shutdown to ensure Tangerine can still reach consensus even without Tangerine consensus algorithm. + +Nodes in the last notary set will vote on the external decentralized blockchain to determine which block height to be the point of recovery. Once a particular block height `h` has more than half of the notary set voted, the recovery consensus is reached. Block height of `h+1` will be an empty block and Tangerine consensus algorithm will continue running at height `h+2`. diff --git a/docs/Remix-IDE.md b/docs/Remix-IDE.md new file mode 100644 index 0000000..5c18440 --- /dev/null +++ b/docs/Remix-IDE.md @@ -0,0 +1 @@ +# Remix IDE diff --git a/docs/Reserved-Network-IDs.md b/docs/Reserved-Network-IDs.md new file mode 100644 index 0000000..5d62ee3 --- /dev/null +++ b/docs/Reserved-Network-IDs.md @@ -0,0 +1,10 @@ +## Reserved Network IDs + + `NetworkID` (or `ChainID`) is a mechanism to separate networks(or chains) owned by different organizations. **Tangerine foundation** reserves these networkIDs: + - **373**: mainnet + - **374**: testnet + - **375, 376**: private testnet during development. + + +### Reference +- [NetworkID SLIP](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) diff --git a/docs/Rules-for-the-node-set.md b/docs/Rules-for-the-node-set.md new file mode 100644 index 0000000..5757d9c --- /dev/null +++ b/docs/Rules-for-the-node-set.md @@ -0,0 +1,41 @@ +# Rules for the Tangerine Network node set + +We introduce the rule for node set and give a brief explanation to the functions in Tangerine Network [governance contract](https://testnet.tangerine.garden/address/0x246FcDE58581e2754f215A523C0718C4BFc8041Fj). + + +## Active condition (permission to be in notary set) + You must deposit enough stake in the governance contract to get the qualification to be selected in the notary set. + Sometimes nodes who violate the rule for notary set will be fined some coin. This leads nodes unqualified to be selected in the notary set. Nodes can be re-qualify after paying the fine. + +## Reward + The reward of each block is calculated as + + block_Reward = mining_Velocity * total_Staked * round_Interval / (365*24*60*60) + + For example, 100 nodes with each staked 1M TAN and mining velocity is 18.75%, the reward of each block is + + 100 * 1M * 18.75% * 1 / (365*24*60*60) = 0.5945586 TAN + + You can find the parameter information via [governance statistic](https://testnet.tangerine.garden/governance) page. + + From the description above, the expected reward for each node in 1 day is + + 100 * 1M * 18.75% * 1 / 365 /100 = 513.7 TAN + +## Penalty +Nodes shall not engage in any of the following conducts: + +1. Forking or trying to fork blocks at the same height by proposing multiple blocks +2. Forking or trying to fork votes by submitting multiple votes in the same iteration in the Byzantine Agreement (BA) +3. Engaging in malicious behaviors in Distributed Key Generation, including without limitation sending wrong secret shares to other nodes, and such behaviors have been complained by other nodes +4. Producing wrong Share-Sig by sending wrong share signature to common reference string (CRS) or in commit-vote +5. Failing to finish distributed key generation (DKG) +6. Failing to propose any blocks during a whole epoch + +For 1. to 4., the entire stake will be confiscated immediately by Tangerine Network. For 5., a fine of the `1 TAN` will be imposed and no blocks can be produced until such fine is paid under the governance contract. For 6., a fine of the `100 TAN` will be imposed and no blocks can be produced until such fine is paid under the governance contract. +<!--- Block Reward*86400/total Node ---> + +Nodes can pay the fine in the governance contract, see [payFine](Governance-Contract.md#pay-fine). + +## Recovery +Currently, Tangerine Network's [recovery](Recovery-Mechanism.md) is built on top of the Ethereum mainnet. All nodes are required to deposit at least **5 Ether** to the same node address. Ether used for recovery will be returned after Tangerine Network successfully recovered. However, if Tangerine Network failed to recover and result in a hard fork, the stakes of nodes that did not deposit enough amount of Ether will be confiscated. diff --git a/docs/Selection-of-the-notary-set-size.md b/docs/Selection-of-the-notary-set-size.md new file mode 100644 index 0000000..5b9ee17 --- /dev/null +++ b/docs/Selection-of-the-notary-set-size.md @@ -0,0 +1,37 @@ +# Selection of the Notary Set Size + +As mention in our consensus algorithm, we follow the hypergeometric distribution to decide the size of notary set. + +Given a node set of size N, the ratio R of Byzantine nodes, and the notary set of size n, then, the probability that more than 1/3 of notary set is Byzantine nodes is + +<p align="center"> + <img src="https://imgur.com/wszheq8.png" width="250"> +</p> + +We set the probability to be 10^-8; that is, there is less than one fault during 10000 years in expectation (notary set is re-selected every hour). +Assume R=1/5. We can derive the proper size of the notary set according to the equation and the result is shown in the following figure. + + +<p align="center"> + <img src="https://i.imgur.com/ylQP4Qu.png"> +</p> + +For convenience, we give two curves to approximate the data points. +The first one is y = 70.5 ln(x) - 264, which is the purple dash line and the second one is y = 74 ln(x) - 264, which is the green dash line. +The following table is the resilience ratio to the Byzantine given the size of notary set and probability 10^-8. + + + +| node set size | notary set size | resilience | notary set size | resilience | +| -------- | -------- | -------- | --- | --- | +| 200 | 110 | 0.199 | 123 | 0.220 | +| 400 | 159 | 0.197 | 174 | 0.207 | +| 600 | 187 | 0.194 | 203 | 0.202 | +| 800 | 208 | 0.197 | 224 | 0.202 | +| 1000 | 223 | 0.197 | 252 | 0.202 | +| 1500 | 252 | 0.199 | 270 | 0.204 | +| 2000 | 272 | 0.199 | 291 | 0.207 | +| 4000 | 321 | 0.207 | 342 | 0.209 | + + +Tangerine mainnet will use y = 70.5 ln(x) - 264 to decide the size of the notary set under different sizes of the node set. diff --git a/docs/Solidity.md b/docs/Solidity.md new file mode 100644 index 0000000..8e124bd --- /dev/null +++ b/docs/Solidity.md @@ -0,0 +1,17 @@ +# Solidity + +## What is Solidity? + +Solidity is an object-oriented, high-level language for implementing smart contracts. Smart contracts are programs which govern the behaviour of accounts within the Ethereum state. + +Solidity was influenced by C++, Python and JavaScript and is designed to target the Ethereum Virtual Machine (EVM). + +Solidity is statically typed, supports inheritance, libraries and complex user-defined types among other features. + +With Solidity you can create contracts for uses such as voting, crowdfunding, blind auctions, and multi-signature wallets. + +When deploying contracts, you should use the latest released version of Solidity. This is because breaking changes as well as new features and bug fixes are introduced regularly. We currently use a 0.x version number [to indicate this fast pace of change](https://semver.org/#spec-item-4). + +## Language Documentation + +For more information, check out the full language documentation of [Solidity](https://solidity.readthedocs.io) diff --git a/docs/System-Spec.md b/docs/System-Spec.md new file mode 100644 index 0000000..c1a13ed --- /dev/null +++ b/docs/System-Spec.md @@ -0,0 +1 @@ +# System Spec diff --git a/docs/Tools-and-Libraries.md b/docs/Tools-and-Libraries.md new file mode 100644 index 0000000..091c7c5 --- /dev/null +++ b/docs/Tools-and-Libraries.md @@ -0,0 +1,10 @@ +# Tools and Libraries + +Here's a list of tools and libraries for developing DApps on Tangerine blockchain platform. + +## Blockchain Explorer + +- [Tangerine Garden](Explorer.md) +Official blockchain explorer and web wallet for Tangerine. You can also check network status and interact with smart contracts in Tangerine Garden. + +## Development Tools diff --git a/docs/Wallet.md b/docs/Wallet.md new file mode 100644 index 0000000..0fa41fa --- /dev/null +++ b/docs/Wallet.md @@ -0,0 +1 @@ +# Tangerine Wallet diff --git a/docs/_sidebar.md b/docs/_sidebar.md new file mode 100644 index 0000000..ad70c40 --- /dev/null +++ b/docs/_sidebar.md @@ -0,0 +1,45 @@ +- Network Access Guide + + - [Create Wallet](Create-Wallet.md) + - [Access to Network](Access-to-Network.md) + +- DApp Development + + - [Development Guide](Dapp-Development-Guide.md) + - [Migrate from Ethereum](Migrate-from-Ethereum.md) + - [Tools and Libraries](Tools-and-Libraries.md) + - [Tangerine Garden](Explorer.md) + +- API + + - [JSON-RPC API](JSON-RPC-API.md) + - [RPC PUB-SUB API](RPC-PUB-SUB.md) + +- Node Operator Guide + + - [Running a BP node](BP-Node-Operation-Guide.md) + - [Running a RPC node](RPC-Node-Operation-Guide.md) + - [Rule for the Tangerine node set](Rules-for-the-node-set.md) + - [Governance Contract](Governance-Contract.md) + +- Fullnode Development Guide + + - [Contribute to Tangerine Fullnode](Contribute-to-Tangerine-Fullnode.md) + - [List of Repositories](List-of-Repositories.md) + +- Technical Documentations + + - [Selection of the Notary Set Size](Selection-of-the-notary-set-size.md) + - [DKG-Tsig Protocol](DKG-TSIG-Protocol.md) + - [On-chain Random Oracle](On-Chain-Random-Oracle.md) + - [Tangerine Cryptoeconomics](Cryptoeconomics.md) + - [Governance Contract Interface](Governance-Contract-Interface.md) + - [Configuration Change](Configuration-Change.md) + - [Recovery Mechanism](Recovery-Mechanism.md) + +- Resource + + - [Blockchain Comparision](Blockchain-Comparison.md) + - [Academic Papers](Papers.md) + - [Reserved NetworkIDs](Reserved-Network-IDs.md) + - [Exchange Integration Guide](Exchange-Integration-Guide.md) diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..123c3c1 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Tangerine Network Wiki</title> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> + <meta name="description" content="Tangerine Network Wiki"> + <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> + <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css"> +</head> +<body> + <div id="app"></div> + <script> + window.$docsify = { + name: 'Tangerine Network Wiki', + loadSidebar: true, + maxLevel: 5, + subMaxLevel: 2, + themeColor: "#e05b21", + ga: 'UA-143831791-1', + search: { + paths: 'auto', + placeholder: { + '/zh-tw/': '搜尋', + '/zh-cn/': '搜索', + '/': 'Search' + } + } + } + </script> + <script src="//unpkg.com/docsify/lib/docsify.min.js"></script> + <script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script> + <script src="//unpkg.com/docsify/lib/plugins/ga.min.js"></script> +</body> +</html> diff --git a/docs/web3-js.md b/docs/web3-js.md new file mode 100644 index 0000000..341ca7f --- /dev/null +++ b/docs/web3-js.md @@ -0,0 +1,16 @@ +# web3.js + +JavaScript library for accessing Tangerine network from browser and Node.js. + +## Usage + +```bash +# Install from npm +> npm install web3 --save +``` + +Get more information for web3.js [here](https://web3js.readthedocs.io/) + +## Github + +[https://github.com/ethereum/web3.js/](https://github.com/ethereum/web3.js/) diff --git a/now.json b/now.json new file mode 100644 index 0000000..7461479 --- /dev/null +++ b/now.json @@ -0,0 +1,4 @@ +{ + "version": 2, + "name": "Tangerine Network Wiki" +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d72112f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3938 @@ +{ + "name": "tangerine-wiki", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "2.1.1" + } + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.6.9", + "regenerator-runtime": "0.10.5" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.6.9", + "regenerator-runtime": "0.11.1" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.3.0", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.2", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.2", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.3" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.3.0", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.1", + "to-object-path": "0.3.0", + "union-value": "1.0.1", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.3", + "fsevents": "1.2.9", + "glob-parent": "2.0.0", + "inherits": "2.0.4", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "clipboard": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", + "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", + "dev": true, + "optional": true, + "requires": { + "good-listener": "1.2.2", + "select": "1.1.2", + "tiny-emitter": "2.1.0" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.2.0", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.4.3", + "xdg-basedir": "3.0.0" + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "1.3.3", + "utils-merge": "1.0.1" + } + }, + "connect-livereload": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz", + "integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cp-file": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-4.2.0.tgz", + "integrity": "sha1-cVNhZjtx7eC23dvDyA4roC5yXsM=", + "dev": true, + "requires": { + "graceful-fs": "4.2.0", + "make-dir": "1.3.0", + "nested-error-stacks": "2.1.0", + "pify": "2.3.0", + "safe-buffer": "5.2.0" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.1" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.5", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "dev": true, + "optional": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "docsify": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/docsify/-/docsify-4.9.4.tgz", + "integrity": "sha512-Xtm6sfrNU7cqOViWMewDhscn0cySF60q2KTKok9OaPmzt6nRkTAIvYU4dj916IT21o/b336Or3vO2hsvmaQzxg==", + "dev": true, + "requires": { + "marked": "0.5.2", + "medium-zoom": "0.4.0", + "opencollective": "1.0.3", + "prismjs": "1.16.0", + "tinydate": "1.1.0", + "tweezer.js": "1.5.0" + } + }, + "docsify-cli": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/docsify-cli/-/docsify-cli-4.3.0.tgz", + "integrity": "sha512-88O1sMeoZv4lb5GPSJzDtOAv2KzBjpQaSqVlVqY+6hGJfb2wpz9PvlUhvlgPq54zu4kPDeCCyUYgqa/llhKg3w==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "connect": "3.7.0", + "connect-livereload": "0.6.1", + "cp-file": "4.2.0", + "docsify": "4.9.4", + "docsify-server-renderer": "4.9.1", + "fs-extra": "2.1.2", + "livereload": "0.7.0", + "lru-cache": "4.1.5", + "opn": "5.5.0", + "serve-static": "1.14.1", + "update-notifier": "2.5.0", + "y18n": "3.2.1", + "yargonaut": "1.1.4", + "yargs": "7.1.0" + } + }, + "docsify-server-renderer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/docsify-server-renderer/-/docsify-server-renderer-4.9.1.tgz", + "integrity": "sha512-JERMD3yEJq38nSim/o1VGBoyqxsRo1VRscafpkx3mT7g07orOg5UARUgztKQNmv+0xnkWsmu+BMr9nsurXmBMQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "docsify": "4.9.4", + "node-fetch": "1.7.3", + "resolve-pathname": "2.2.0" + }, + "dependencies": { + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + } + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.4" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.24", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "figlet": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.2.3.tgz", + "integrity": "sha512-+F5zdvZ66j77b8x2KCPvWUHC0UCKUMWrewxmewgPlagp3wmDpcrHMbyv/ygq/6xoxBPGQA+UJU3SMoBzKoROQQ==", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.1", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.3", + "statuses": "1.5.0", + "unpipe": "1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "dev": true, + "requires": { + "graceful-fs": "4.2.0", + "jsonfile": "2.4.0" + } + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.14.0", + "node-pre-gyp": "0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.3.5" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.3" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.3.5" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "4.1.1", + "iconv-lite": "0.4.24", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.3.0", + "nopt": "4.0.1", + "npm-packlist": "1.4.1", + "npmlog": "4.1.2", + "rc": "1.2.8", + "rimraf": "2.6.3", + "semver": "5.7.0", + "tar": "4.4.8" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.6" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.1.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.5", + "minizlib": "1.2.1", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "1.3.5" + } + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "dev": true, + "optional": true, + "requires": { + "delegate": "3.2.0" + } + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.2.0", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", + "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": "1.5.0", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", + "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "chalk": "1.1.3", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.14", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx": "4.1.0", + "string-width": "2.1.1", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.13.1" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "1.6.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.2.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "4.0.1" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "livereload": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.7.0.tgz", + "integrity": "sha512-PHnIGczQEvmCctDvRTWylA+1wSwE0/eFm+LkNhlmlAFus/aCRlVE97UOLOf6TUGLmZyfg7z7twG37ZiOgNJAyQ==", + "dev": true, + "requires": { + "chokidar": "1.7.0", + "opts": "1.2.6", + "ws": "1.1.5" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.2.0", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "marked": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.5.2.tgz", + "integrity": "sha512-fdZvBa7/vSQIZCi4uuwo2N3q+7jJURpMVCcbaX0S1Mg65WZ5ilXvC67MviJAsdjqqgD+CEq4RKo5AYGgINkVAA==", + "dev": true + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "medium-zoom": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-0.4.0.tgz", + "integrity": "sha512-0z7yMfd6I1BTCAa8QaR4cp5AqDkQD571GzhHIbbfefKEssGLSvs+4Xai/itOAncm4FBlF5gUoMQ22yW9/f8Sig==", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, + "node-fetch": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", + "dev": true, + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "2.7.1", + "resolve": "1.11.1", + "semver": "5.7.0", + "validate-npm-package-license": "3.0.4" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "now": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/now/-/now-15.8.0.tgz", + "integrity": "sha512-0RfVPAyzI6oR6IN0oxsMrANXXvyVZ34//VDGZ+Z4xW4DxtAxB5bls2m1VXpqmyu2Asc7RrdHOL9XthNE+70OXA==", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "opencollective": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", + "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", + "dev": true, + "requires": { + "babel-polyfill": "6.23.0", + "chalk": "1.1.3", + "inquirer": "3.0.6", + "minimist": "1.2.0", + "node-fetch": "1.6.3", + "opn": "4.0.2" + }, + "dependencies": { + "opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + } + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "1.1.0" + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "dev": true + }, + "opts": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/opts/-/opts-1.2.6.tgz", + "integrity": "sha1-0YXAQlz9652h0YKQi2W1wCOP67M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.4.0", + "registry-url": "3.1.0", + "semver": "5.7.0" + } + }, + "parent-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", + "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.2" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "prismjs": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.16.0.tgz", + "integrity": "sha512-OA4MKxjFZHSvZcisLGe14THYsug/nF6O1f0pAJc0KN0wTyAcLqmsbE+lTGKSpyh+9pEW57+k6pg2AfYR+coyHA==", + "dev": true, + "requires": { + "clipboard": "2.0.4" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.4" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.5.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.4", + "isarray": "1.0.0", + "process-nextick-args": "2.0.1", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "4.2.0", + "micromatch": "3.1.10", + "readable-stream": "2.3.6" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "dev": true, + "requires": { + "rc": "1.2.8", + "safe-buffer": "5.2.0" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "1.2.8" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "1.0.6" + } + }, + "resolve-pathname": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", + "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", + "dev": true + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "5.7.0" + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.7.3", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "2.3.0", + "range-parser": "1.2.1", + "statuses": "1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.5" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.2.0", + "spdx-license-ids": "3.0.5" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "0.7.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "dev": true, + "optional": true + }, + "tinydate": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.1.0.tgz", + "integrity": "sha512-YF6YTOyBRHX4b3EtEI0W/mROcv82Gt6VccmVuSAkRV3FNORug2457wSGvT2cThbfuctQvVSmC5GobGheScxtIw==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tweezer.js": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/tweezer.js/-/tweezer.js-1.5.0.tgz", + "integrity": "sha512-aSiJz7rGWNAQq7hjMK9ZYDuEawXupcCWgl3woQQSoDP2Oh8O4srWb/uO1PzzHIsrPEOqrjJ2sUb9FERfzuBabQ==", + "dev": true + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "2.0.1" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "1.3.0", + "chalk": "2.4.2", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.2.1", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.3" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "3.1.0", + "spdx-expression-parse": "3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "2.1.1" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "4.2.0", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "dev": true, + "requires": { + "options": "0.0.6", + "ultron": "1.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargonaut": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz", + "integrity": "sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "figlet": "1.2.3", + "parent-require": "1.0.0" + } + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9dfb872 --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "tangerine-wiki", + "version": "1.0.0", + "description": "Tangerine Network Wiki", + "main": "index.js", + "directories": { + "doc": "docs" + }, + "dependencies": {}, + "devDependencies": { + "docsify-cli": "^4.3.0", + "now": "^15.8.0" + }, + "scripts": { + "start": "docsify start docs", + "deploy": "now -p" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@gitlab.com/byzantine-lab/wiki.git" + }, + "keywords": [ + "Tangerine", + "Network", + "Blockchain", + "DLT" + ], + "author": "Wei-Ning Huang <w@byzantine-lab.io>", + "license": "ISC", + "bugs": { + "url": "https://gitlab.com/byzantine-lab/wiki/issues" + }, + "homepage": "https://gitlab.com/byzantine-lab/wiki#README" +} |